diff --git a/DEPS b/DEPS index 3601242c..25c6f5b 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': 'e21616804a5af69a3e74748669c5d4f100d92102', + 'skia_revision': '51874e3e371230e2cc02912ed0c9ddb569e48532', # 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': '5671f8b940b0fcdb550e318e449ded0f866e935a', + 'v8_revision': '2f88b9b20539a240a74256f647f249f32b355e9e', # 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,11 +141,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '896e7ded5f25c36f802ed7dd839f8790d16aed23', + 'angle_revision': '27f115aa0b8098feb21b85df8694b796be360c98', # 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': 'd39c96e96a31e2c9e386f5a6fc2278468c22d70e', + 'swiftshader_revision': '0e3d328ac338c4c9474f5d967455ff501bd869cb', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # 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': 'de8da4841bc3d1ed020d798d5a7fd6fb3d817fa1', + 'nacl_revision': '2c300847c7700af6948ad78e79ccd21bd7ba0c14', # 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': '144122958b2879a06cdc9098d63a3703be8b181a', + 'catapult_revision': '810aaa1e18466131f6a75b1f631fb5b0dd81f344', # 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' + '@' + '0b63029f96dd8e791b832212638d3356cd8def40', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c012fdb54ccb7b73fe5e83bce907fc8c62217737', 'condition': 'checkout_linux', }, @@ -978,7 +978,7 @@ Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + 'f7ce90e84f5aa9acfbc9b7ca04e567bf471e5bcd', 'src/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'b10cc9f714e6da621c94de0f1e6090c176f876ae', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '69c72a6dfe1d1ef5677db03920518638f535591f', 'src/third_party/icu4j': { 'packages': [ @@ -1172,7 +1172,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '9ea63e7d30e8f356cc8a4712eee859ce7bf059cf', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'e382e0ed7613c7aef564518f2e8b58efe6f7f7c1', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1343,7 +1343,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '688fbfe33779392aa210d67d4aa12cb012f112c2', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'f75d458951d097e116e710fc70ead3344ad2c259', + Var('webrtc_git') + '/src.git' + '@' + '1c747f5717bcbde029a2d496832ee52388dbda05', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/WATCHLISTS b/WATCHLISTS index 2aa65f0a..b1b0279 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -45,9 +45,6 @@ 'filepath': 'third_party/android_deps/' \ '|tools/android/roll/android_deps/' }, - 'android_features': { - 'filepath': 'chrome/android/features/' - }, 'android_infobars': { 'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/infobar/' }, @@ -1825,7 +1822,6 @@ 'wnwen+watch@chromium.org'], 'android_crazy_linker': ['johnmaguire+watch@google.com'], 'android_deps': ['wnwen+watch@chromium.org'], - 'android_features': ['tiborg+watch@chromium.org'], 'android_infobars': ['dfalcantara+watch@chromium.org'], 'android_infra': ['agrieve+watch@chromium.org', 'estevenson+watch@chromium.org',
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index 0a8e33ab..1231b076 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -454,14 +454,12 @@ # differentiate only by ABI. Each library has an app-bundle ("_base") # variant. if (current_toolchain == android_secondary_abi_toolchain) { - if (enable_64_bit_browser) { - # These targets are the 32-bit WebView libraries that pair with a 64-bit - # browser. They are suffixed with _64 because their names must mach the - # 64-bit browser library. - webview_library("monochrome_64") { - } - webview_library("monochrome_64_base") { - } + # These targets are the 32-bit WebView libraries that pair with a 64-bit + # browser. They are suffixed with _64 because their names must mach the + # 64-bit browser library. + webview_library("monochrome_64") { + } + webview_library("monochrome_64_base") { } } else { # Inverse of the others above, for the original 32-bit case.
diff --git a/android_webview/docs/quick-start.md b/android_webview/docs/quick-start.md index 7fe0e242..aee78cb 100644 --- a/android_webview/docs/quick-start.md +++ b/android_webview/docs/quick-start.md
@@ -68,13 +68,8 @@ # Install the APK $ out/Default/bin/system_webview_apk install -# If you don't have `adb` in your path, you can source this file to use -# the copy from chromium's Android SDK. -$ source build/android/envsetup.sh - -# Tell Android platform to load a WebView implementation from this APK. -# Use the package name from GN args. -$ adb shell cmd webviewupdate set-webview-implementation com.google.android.apps.chrome +# Tell Android platform to load a WebView implementation from this APK +$ out/Default/bin/system_webview_apk set-webview-provider ``` ## Start running an app
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc index 88610f81..294c6f47 100644 --- a/ash/accessibility/accessibility_controller.cc +++ b/ash/accessibility/accessibility_controller.cc
@@ -42,7 +42,6 @@ #include "ui/aura/window.h" #include "ui/base/cursor/cursor_type.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/ui_base_features.h" #include "ui/keyboard/keyboard_util.h" #include "ui/message_center/message_center.h" #include "ui/message_center/public/cpp/notifier_id.h" @@ -1257,23 +1256,7 @@ NotifyAccessibilityStatusChanged(); - const bool was_enabled = keyboard::IsKeyboardEnabled(); keyboard::SetAccessibilityKeyboardEnabled(enabled); - - if (::features::IsMultiProcessMash()) { - // TODO(mash): Support on-screen keyboard. See https://crbug.com/646565. - NOTIMPLEMENTED(); - return; - } - - // Note that there are two versions of the on-screen keyboard. A full layout - // is provided for accessibility, which includes sticky modifier keys to - // enable typing of hotkeys. A compact version is used in tablet mode to - // provide a layout with larger keys to facilitate touch typing. In the event - // that the a11y keyboard is being disabled, an on-screen keyboard might still - // be enabled and a forced reset is required to pick up the layout change. - if (was_enabled) - Shell::Get()->ash_keyboard_controller()->RebuildKeyboardIfEnabled(); } void AccessibilityController::GetBatteryDescription(
diff --git a/ash/accessibility/accessibility_controller_unittest.cc b/ash/accessibility/accessibility_controller_unittest.cc index ae3dc44..59210e2 100644 --- a/ash/accessibility/accessibility_controller_unittest.cc +++ b/ash/accessibility/accessibility_controller_unittest.cc
@@ -21,9 +21,7 @@ #include "base/strings/utf_string_conversions.h" #include "chromeos/dbus/power/fake_power_manager_client.h" #include "components/prefs/pref_service.h" -#include "ui/keyboard/keyboard_controller.h" #include "ui/keyboard/keyboard_util.h" -#include "ui/keyboard/test/test_keyboard_controller_observer.h" #include "ui/message_center/message_center.h" using message_center::MessageCenter; @@ -295,29 +293,6 @@ controller->RemoveObserver(&observer); } -// See https://crbug.com/946358. -TEST_F(AccessibilityControllerTest, RebuildsVirtualKeyboardWhenPrefChanges) { - AccessibilityController* controller = - Shell::Get()->accessibility_controller(); - EXPECT_FALSE(controller->virtual_keyboard_enabled()); - - // Virtual keyboard enabled with compact layout. - keyboard::SetTouchKeyboardEnabled(true); - - keyboard::TestKeyboardControllerObserver observer; - keyboard::KeyboardController::Get()->AddObserver(&observer); - - // Virtual keyboard should rebuild to switch to a11y layout. - controller->SetVirtualKeyboardEnabled(true); - EXPECT_EQ(1, observer.enabled_count); - - // Virtual keyboard should rebuild to switch back to compact layout. - controller->SetVirtualKeyboardEnabled(false); - EXPECT_EQ(2, observer.enabled_count); - - keyboard::KeyboardController::Get()->RemoveObserver(&observer); -} - // Tests that ash's controller gets shutdown sound duration properly from // remote client. TEST_F(AccessibilityControllerTest, GetShutdownSoundDuration) {
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index cf5f543..a7433ab 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -133,7 +133,7 @@ Back </message> <message name="IDS_ASH_SHELF_OVERFLOW_NAME" desc="The title used for the Ash overflow button in the shelf"> - Overflow button + Overflow </message> <message name="IDS_ASH_SHELF_CONTEXT_MENU_AUTO_HIDE" desc="Title of the menu item in the context menu for auto-hiding the shelf when the current window is not maximized"> Autohide shelf
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index 947b945..52684f9a 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -840,6 +840,10 @@ const TargetBounds& target_bounds, bool animate, ui::ImplicitAnimationObserver* observer) { + // Do not update the work area during overview animation. + if (suspend_visibility_update_) + return; + StatusAreaWidget* status_widget = shelf_widget_->status_area_widget(); base::AutoReset<bool> auto_reset_updating_bounds(&updating_bounds_, true); {
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index 0a654f73..0bae2eaf 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -62,6 +62,7 @@ #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/display/display.h" #include "ui/display/display_layout.h" +#include "ui/display/display_observer.h" #include "ui/display/manager/display_manager.h" #include "ui/display/screen.h" #include "ui/display/test/display_manager_test_api.h" @@ -271,23 +272,25 @@ DISALLOW_COPY_AND_ASSIGN(ShelfDragCallback); }; -class ShelfLayoutObserverTest : public ShelfLayoutManagerObserver { +class TestDisplayObserver : public display::DisplayObserver { public: - ShelfLayoutObserverTest() : changed_auto_hide_state_(false) {} + TestDisplayObserver() { display::Screen::GetScreen()->AddObserver(this); } + ~TestDisplayObserver() override { + display::Screen::GetScreen()->RemoveObserver(this); + } - ~ShelfLayoutObserverTest() override = default; - - bool changed_auto_hide_state() const { return changed_auto_hide_state_; } + int metrics_change_count() const { return metrics_change_count_; } private: // ShelfLayoutManagerObserver: - void OnAutoHideStateChanged(ShelfAutoHideState new_state) override { - changed_auto_hide_state_ = true; + void OnDisplayMetricsChanged(const display::Display& display, + uint32_t changed_metrics) override { + metrics_change_count_++; } - bool changed_auto_hide_state_; + int metrics_change_count_ = 0; - DISALLOW_COPY_AND_ASSIGN(ShelfLayoutObserverTest); + DISALLOW_COPY_AND_ASSIGN(TestDisplayObserver); }; class WallpaperShownWaiter : public WallpaperControllerObserver { @@ -2972,4 +2975,70 @@ display::Screen::GetScreen()->GetPrimaryDisplay().work_area()); } +namespace { + +class OverviewAnimationWaiter : public OverviewObserver { + public: + OverviewAnimationWaiter() { + Shell::Get()->overview_controller()->AddObserver(this); + } + + ~OverviewAnimationWaiter() override { + Shell::Get()->overview_controller()->RemoveObserver(this); + } + + // Note this could only be called once because RunLoop would not run after + // Quit is called. Create a new instance if there's need to wait again. + void Wait() { run_loop_.Run(); } + + // OverviewObserver: + void OnOverviewModeStartingAnimationComplete(bool cancel) override { + run_loop_.Quit(); + } + void OnOverviewModeEndingAnimationComplete(bool cancel) override { + run_loop_.Quit(); + } + + private: + base::RunLoop run_loop_; + + DISALLOW_COPY_AND_ASSIGN(OverviewAnimationWaiter); +}; + +} // namespace + +// Make sure we don't update the work area during overview animation +// (crbug.com/947343). +TEST_F(ShelfLayoutManagerTest, NoShelfUpdateDuringOverviewAnimation) { + // Finish lid detection task. + base::RunLoop().RunUntilIdle(); + TabletModeControllerTestApi().EnterTabletMode(); + // Run overview animations. + ui::ScopedAnimationDurationScaleMode regular_animations( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + + std::unique_ptr<aura::Window> window1(AshTestBase::CreateTestWindow()); + std::unique_ptr<aura::Window> fullscreen(AshTestBase::CreateTestWindow()); + fullscreen->SetProperty(aura::client::kShowStateKey, + ui::SHOW_STATE_FULLSCREEN); + wm::ActivateWindow(fullscreen.get()); + + OverviewController* overview_controller = Shell::Get()->overview_controller(); + TestDisplayObserver observer; + { + OverviewAnimationWaiter waiter; + overview_controller->ToggleOverview(); + waiter.Wait(); + } + ASSERT_TRUE(TabletModeControllerTestApi().IsTabletModeStarted()); + EXPECT_EQ(0, observer.metrics_change_count()); + { + OverviewAnimationWaiter waiter; + overview_controller->ToggleOverview(); + waiter.Wait(); + } + ASSERT_TRUE(TabletModeControllerTestApi().IsTabletModeStarted()); + EXPECT_EQ(0, observer.metrics_change_count()); +} + } // namespace ash
diff --git a/ash/system/unified/OWNERS b/ash/system/unified/OWNERS new file mode 100644 index 0000000..430ce8a --- /dev/null +++ b/ash/system/unified/OWNERS
@@ -0,0 +1,2 @@ +tetsui@chromium.org +tengs@chromium.org
diff --git a/base/BUILD.gn b/base/BUILD.gn index 619eaceb..fadacd7 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -626,6 +626,7 @@ "process/process_win.cc", "profiler/frame.cc", "profiler/frame.h", + "profiler/native_unwinder.h", "profiler/native_unwinder_mac.cc", "profiler/native_unwinder_mac.h", "profiler/native_unwinder_win.cc", @@ -645,7 +646,6 @@ "profiler/thread_delegate_mac.h", "profiler/thread_delegate_win.cc", "profiler/thread_delegate_win.h", - "profiler/unwind_result.h", "profiler/unwinder.h", "rand_util.cc", "rand_util.h",
diff --git a/base/profiler/native_unwinder.h b/base/profiler/native_unwinder.h new file mode 100644 index 0000000..f26c5ad2 --- /dev/null +++ b/base/profiler/native_unwinder.h
@@ -0,0 +1,20 @@ +// 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 BASE_PROFILER_NATIVE_UNWINDER_H_ +#define BASE_PROFILER_NATIVE_UNWINDER_H_ + +#include <memory> + +namespace base { + +class ModuleCache; +class Unwinder; + +// Creates the native unwinder for the platform. +std::unique_ptr<Unwinder> CreateNativeUnwinder(ModuleCache* module_cache); + +} // namespace base + +#endif // BASE_PROFILER_NATIVE_UNWINDER_H_
diff --git a/base/profiler/native_unwinder_mac.cc b/base/profiler/native_unwinder_mac.cc index a91adb3..1cf2f6d1 100644 --- a/base/profiler/native_unwinder_mac.cc +++ b/base/profiler/native_unwinder_mac.cc
@@ -11,6 +11,7 @@ #include <sys/ptrace.h> #include "base/logging.h" +#include "base/profiler/native_unwinder.h" #include "base/profiler/profile_builder.h" #include "base/sampling_heap_profiler/module_cache.h" @@ -138,7 +139,7 @@ uintptr_t stack_top, ModuleCache* module_cache, std::vector<Frame>* stack) const { - // We expect the frame corresponding to the |thread_context| register state to + // We expect the frame correponding to the |thread_context| register state to // exist within |stack|. DCHECK_GT(stack->size(), 0u); @@ -270,4 +271,8 @@ return UnwindResult::COMPLETED; } +std::unique_ptr<Unwinder> CreateNativeUnwinder(ModuleCache* module_cache) { + return std::make_unique<NativeUnwinderMac>(module_cache); +} + } // namespace base
diff --git a/base/profiler/native_unwinder_mac.h b/base/profiler/native_unwinder_mac.h index 00cc318c..af44a7e9 100644 --- a/base/profiler/native_unwinder_mac.h +++ b/base/profiler/native_unwinder_mac.h
@@ -29,7 +29,7 @@ // Cached pointer to the libsystem_kernel module. const ModuleCache::Module* const libsystem_kernel_module_; - // The address range of _sigtramp(), the signal trampoline function. + // The address range of |_sigtramp|, the signal trampoline function. uintptr_t sigtramp_start_; uintptr_t sigtramp_end_; };
diff --git a/base/profiler/native_unwinder_win.cc b/base/profiler/native_unwinder_win.cc index 4736fd2..5b255c4 100644 --- a/base/profiler/native_unwinder_win.cc +++ b/base/profiler/native_unwinder_win.cc
@@ -4,6 +4,7 @@ #include "base/profiler/native_unwinder_win.h" +#include "base/profiler/native_unwinder.h" #include "base/profiler/win32_stack_frame_unwinder.h" namespace base { @@ -19,7 +20,7 @@ uintptr_t stack_top, ModuleCache* module_cache, std::vector<Frame>* stack) const { - // We expect the frame corresponding to the |thread_context| register state to + // We expect the frame correponding to the |thread_context| register state to // exist within |stack|. DCHECK_GT(stack->size(), 0u); @@ -64,4 +65,8 @@ return UnwindResult::COMPLETED; } +std::unique_ptr<Unwinder> CreateNativeUnwinder(ModuleCache* module_cache) { + return std::make_unique<NativeUnwinderWin>(); +} + } // namespace base
diff --git a/base/profiler/native_unwinder_win.h b/base/profiler/native_unwinder_win.h index a32ad40..979c2c4 100644 --- a/base/profiler/native_unwinder_win.h +++ b/base/profiler/native_unwinder_win.h
@@ -5,6 +5,7 @@ #ifndef BASE_PROFILER_NATIVE_UNWINDER_WIN_H_ #define BASE_PROFILER_NATIVE_UNWINDER_WIN_H_ +#include "base/macros.h" #include "base/profiler/unwinder.h" namespace base {
diff --git a/base/profiler/stack_sampler_impl.cc b/base/profiler/stack_sampler_impl.cc index 8477bbc..a1153c3 100644 --- a/base/profiler/stack_sampler_impl.cc +++ b/base/profiler/stack_sampler_impl.cc
@@ -9,6 +9,7 @@ #include "base/logging.h" #include "base/profiler/profile_builder.h" #include "base/profiler/thread_delegate.h" +#include "base/profiler/unwinder.h" // IMPORTANT NOTE: Some functions within this implementation are invoked while // the target thread is suspended so it must not do any allocation from the @@ -74,9 +75,11 @@ StackSamplerImpl::StackSamplerImpl( std::unique_ptr<ThreadDelegate> thread_delegate, + std::unique_ptr<Unwinder> native_unwinder, ModuleCache* module_cache, StackSamplerTestDelegate* test_delegate) : thread_delegate_(std::move(thread_delegate)), + native_unwinder_(std::move(native_unwinder)), module_cache_(module_cache), test_delegate_(test_delegate) {} @@ -168,8 +171,7 @@ module_cache_->GetModuleForAddress( RegisterContextInstructionPointer(thread_context))); - thread_delegate_->WalkNativeFrames(thread_context, stack_top, module_cache_, - &stack); + native_unwinder_->TryUnwind(thread_context, stack_top, module_cache_, &stack); return stack; }
diff --git a/base/profiler/stack_sampler_impl.h b/base/profiler/stack_sampler_impl.h index 28d9556..926c4a3 100644 --- a/base/profiler/stack_sampler_impl.h +++ b/base/profiler/stack_sampler_impl.h
@@ -15,12 +15,14 @@ namespace base { class ThreadDelegate; +class Unwinder; // Cross-platform stack sampler implementation. Delegates to ThreadDelegate for // platform-specific implementation. class BASE_EXPORT StackSamplerImpl : public StackSampler { public: StackSamplerImpl(std::unique_ptr<ThreadDelegate> delegate, + std::unique_ptr<Unwinder> native_unwinder, ModuleCache* module_cache, StackSamplerTestDelegate* test_delegate = nullptr); ~StackSamplerImpl() override; @@ -42,6 +44,7 @@ uintptr_t stack_top); const std::unique_ptr<ThreadDelegate> thread_delegate_; + const std::unique_ptr<Unwinder> native_unwinder_; ModuleCache* const module_cache_; StackSamplerTestDelegate* const test_delegate_; };
diff --git a/base/profiler/stack_sampler_impl_unittest.cc b/base/profiler/stack_sampler_impl_unittest.cc index 6b6b95b..2a2e808e 100644 --- a/base/profiler/stack_sampler_impl_unittest.cc +++ b/base/profiler/stack_sampler_impl_unittest.cc
@@ -8,6 +8,7 @@ #include "base/profiler/profile_builder.h" #include "base/profiler/stack_sampler_impl.h" #include "base/profiler/thread_delegate.h" +#include "base/profiler/unwinder.h" #include "base/sampling_heap_profiler/module_cache.h" #include "build/build_config.h" #include "testing/gmock/include/gmock/gmock.h" @@ -52,19 +53,10 @@ }; TestThreadDelegate(const std::vector<uintptr_t>& fake_stack, - // Vector to fill in with the copied stack. - std::vector<uintptr_t>* stack_copy = nullptr, - // Variable to fill in with the bottom address of the - // copied stack. This will be different than - // &(*stack_copy)[0] because |stack_copy| is a copy of the - // copy so does not share memory with the actual copy. - uintptr_t* stack_copy_bottom = nullptr, // The register context will be initialized to // *|thread_context| if non-null. RegisterContext* thread_context = nullptr) : fake_stack_(fake_stack), - stack_copy_(stack_copy), - stack_copy_bottom_(stack_copy_bottom), thread_context_(thread_context) {} TestThreadDelegate(const TestThreadDelegate&) = delete; @@ -96,14 +88,37 @@ return {&RegisterContextFramePointer(thread_context)}; } - UnwindResult WalkNativeFrames(RegisterContext* thread_context, - uintptr_t stack_top, - ModuleCache* module_cache, - std::vector<Frame>* stack) override { + private: + // Must be a reference to retain the underlying allocation from the vector + // passed to the constructor. + const std::vector<uintptr_t>& fake_stack_; + RegisterContext* thread_context_; +}; + +// Trivial unwinder implementation for testing. +class TestUnwinder : public Unwinder { + public: + TestUnwinder(size_t stack_size = 0, + std::vector<uintptr_t>* stack_copy = nullptr, + // Variable to fill in with the bottom address of the + // copied stack. This will be different than + // &(*stack_copy)[0] because |stack_copy| is a copy of the + // copy so does not share memory with the actual copy. + uintptr_t* stack_copy_bottom = nullptr) + : stack_size_(stack_size), + stack_copy_(stack_copy), + stack_copy_bottom_(stack_copy_bottom) {} + + bool CanUnwindFrom(const Frame* current_frame) const override { return true; } + + UnwindResult TryUnwind(RegisterContext* thread_context, + uintptr_t stack_top, + ModuleCache* module_cache, + std::vector<Frame>* stack) const override { if (stack_copy_) { auto* bottom = reinterpret_cast<uintptr_t*>( RegisterContextStackPointer(thread_context)); - auto* top = bottom + fake_stack_.size(); + auto* top = bottom + stack_size_; *stack_copy_ = std::vector<uintptr_t>(bottom, top); } if (stack_copy_bottom_) @@ -112,12 +127,9 @@ } private: - // Must be a reference to retain the underlying allocation from the vector - // passed to the constructor. - const std::vector<uintptr_t>& fake_stack_; + size_t stack_size_; std::vector<uintptr_t>* stack_copy_; uintptr_t* stack_copy_bottom_; - RegisterContext* thread_context_; }; class TestModule : public ModuleCache::Module { @@ -153,7 +165,8 @@ InjectModuleForContextInstructionPointer(stack, &module_cache); std::vector<uintptr_t> stack_copy; StackSamplerImpl stack_sampler_impl( - std::make_unique<TestThreadDelegate>(stack, &stack_copy), &module_cache); + std::make_unique<TestThreadDelegate>(stack), + std::make_unique<TestUnwinder>(stack.size(), &stack_copy), &module_cache); std::unique_ptr<StackSampler::StackBuffer> stack_buffer = std::make_unique<StackSampler::StackBuffer>(stack.size() * @@ -170,7 +183,8 @@ InjectModuleForContextInstructionPointer(stack, &module_cache); std::vector<uintptr_t> stack_copy; StackSamplerImpl stack_sampler_impl( - std::make_unique<TestThreadDelegate>(stack, &stack_copy), &module_cache); + std::make_unique<TestThreadDelegate>(stack), + std::make_unique<TestUnwinder>(stack.size(), &stack_copy), &module_cache); std::unique_ptr<StackSampler::StackBuffer> stack_buffer = std::make_unique<StackSampler::StackBuffer>((stack.size() - 1) * @@ -196,8 +210,9 @@ std::vector<uintptr_t> stack_copy; uintptr_t stack_copy_bottom; StackSamplerImpl stack_sampler_impl( - std::make_unique<TestThreadDelegate>(stack, &stack_copy, - &stack_copy_bottom), + std::make_unique<TestThreadDelegate>(stack), + std::make_unique<TestUnwinder>(stack.size(), &stack_copy, + &stack_copy_bottom), &module_cache); std::unique_ptr<StackSampler::StackBuffer> stack_buffer = @@ -220,8 +235,8 @@ RegisterContextFramePointer(&thread_context) = reinterpret_cast<uintptr_t>(&stack[1]); StackSamplerImpl stack_sampler_impl( - std::make_unique<TestThreadDelegate>(stack, nullptr, &stack_copy_bottom, - &thread_context), + std::make_unique<TestThreadDelegate>(stack, &thread_context), + std::make_unique<TestUnwinder>(stack.size(), nullptr, &stack_copy_bottom), &module_cache); std::unique_ptr<StackSampler::StackBuffer> stack_buffer =
diff --git a/base/profiler/stack_sampler_mac.cc b/base/profiler/stack_sampler_mac.cc index 3bb8f9b4..54ca505e 100644 --- a/base/profiler/stack_sampler_mac.cc +++ b/base/profiler/stack_sampler_mac.cc
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <memory> - #include "base/profiler/stack_sampler.h" + +#include "base/profiler/native_unwinder_mac.h" #include "base/profiler/stack_sampler_impl.h" #include "base/profiler/thread_delegate_mac.h" @@ -16,8 +16,9 @@ ModuleCache* module_cache, StackSamplerTestDelegate* test_delegate) { return std::make_unique<StackSamplerImpl>( - std::make_unique<ThreadDelegateMac>(thread_id, module_cache), - module_cache, test_delegate); + std::make_unique<ThreadDelegateMac>(thread_id), + std::make_unique<NativeUnwinderMac>(module_cache), module_cache, + test_delegate); } // static
diff --git a/base/profiler/stack_sampler_win.cc b/base/profiler/stack_sampler_win.cc index 2edec59..214cf0d 100644 --- a/base/profiler/stack_sampler_win.cc +++ b/base/profiler/stack_sampler_win.cc
@@ -4,6 +4,7 @@ #include "base/profiler/stack_sampler.h" +#include "base/profiler/native_unwinder_win.h" #include "base/profiler/stack_sampler_impl.h" #include "base/profiler/thread_delegate_win.h" #include "build/build_config.h" @@ -17,8 +18,8 @@ StackSamplerTestDelegate* test_delegate) { #if defined(ARCH_CPU_X86_64) return std::make_unique<StackSamplerImpl>( - std::make_unique<ThreadDelegateWin>(thread_id), module_cache, - test_delegate); + std::make_unique<ThreadDelegateWin>(thread_id), + std::make_unique<NativeUnwinderWin>(), module_cache, test_delegate); #else return nullptr; #endif
diff --git a/base/profiler/thread_delegate.h b/base/profiler/thread_delegate.h index 35072a4a..d0f0f02 100644 --- a/base/profiler/thread_delegate.h +++ b/base/profiler/thread_delegate.h
@@ -10,7 +10,6 @@ #include "base/base_export.h" #include "base/profiler/frame.h" #include "base/profiler/register_context.h" -#include "base/profiler/unwind_result.h" namespace base { @@ -66,16 +65,6 @@ // May heap allocate. virtual std::vector<uintptr_t*> GetRegistersToRewrite( RegisterContext* thread_context) = 0; - - // Walks the native frames on the stack pointed to by the stack pointer in - // |thread_context|, appending the frames to |stack|. When invoked - // stack->back() contains the frame corresponding to the state in - // |thread_context|. - // TODO(wittman): Move the unwinding support into a separate UnwindDelegate. - virtual UnwindResult WalkNativeFrames(RegisterContext* thread_context, - uintptr_t stack_top, - ModuleCache* module_cache, - std::vector<Frame>* stack) = 0; }; } // namespace base
diff --git a/base/profiler/thread_delegate_mac.cc b/base/profiler/thread_delegate_mac.cc index 4342316..7632c4ef 100644 --- a/base/profiler/thread_delegate_mac.cc +++ b/base/profiler/thread_delegate_mac.cc
@@ -58,12 +58,10 @@ // ThreadDelegateMac ---------------------------------------------------------- -ThreadDelegateMac::ThreadDelegateMac(mach_port_t thread_port, - ModuleCache* module_cache) +ThreadDelegateMac::ThreadDelegateMac(mach_port_t thread_port) : thread_port_(thread_port), thread_stack_base_address_(reinterpret_cast<uintptr_t>( - pthread_get_stackaddr_np(pthread_from_mach_thread_np(thread_port)))), - native_unwinder_(module_cache) { + pthread_get_stackaddr_np(pthread_from_mach_thread_np(thread_port)))) { // This class suspends threads, and those threads might be suspended in dyld. // Therefore, for all the system functions that might be linked in dynamically // that are used while threads are suspended, make calls to them to make sure @@ -103,13 +101,4 @@ &AsUintPtr(&thread_context->__r15)}; } -UnwindResult ThreadDelegateMac::WalkNativeFrames( - x86_thread_state64_t* thread_context, - uintptr_t stack_top, - ModuleCache* module_cache, - std::vector<Frame>* stack) { - return native_unwinder_.TryUnwind(thread_context, stack_top, module_cache, - stack); -} - } // namespace base
diff --git a/base/profiler/thread_delegate_mac.h b/base/profiler/thread_delegate_mac.h index 098b2a90..1ff2497 100644 --- a/base/profiler/thread_delegate_mac.h +++ b/base/profiler/thread_delegate_mac.h
@@ -33,7 +33,7 @@ mach_port_t thread_port_; }; - ThreadDelegateMac(mach_port_t thread_port, ModuleCache* module_cache); + ThreadDelegateMac(mach_port_t thread_port); ~ThreadDelegateMac() override; ThreadDelegateMac(const ThreadDelegateMac&) = delete; @@ -48,20 +48,12 @@ std::vector<uintptr_t*> GetRegistersToRewrite( x86_thread_state64_t* thread_context) override; - UnwindResult WalkNativeFrames(x86_thread_state64_t* thread_context, - uintptr_t stack_top, - ModuleCache* module_cache, - std::vector<Frame>* stack) override; - private: // Weak reference: Mach port for thread being profiled. mach_port_t thread_port_; // The stack base address corresponding to |thread_port_|. const uintptr_t thread_stack_base_address_; - - // The unwinder for native stack frames. - NativeUnwinderMac native_unwinder_; }; } // namespace base
diff --git a/base/profiler/thread_delegate_win.cc b/base/profiler/thread_delegate_win.cc index 50045cd..c249ad4 100644 --- a/base/profiler/thread_delegate_win.cc +++ b/base/profiler/thread_delegate_win.cc
@@ -200,12 +200,4 @@ }; } -UnwindResult ThreadDelegateWin::WalkNativeFrames(CONTEXT* thread_context, - uintptr_t stack_top, - ModuleCache* module_cache, - std::vector<Frame>* stack) { - NativeUnwinderWin unwinder; - return unwinder.TryUnwind(thread_context, stack_top, module_cache, stack); -} - } // namespace base
diff --git a/base/profiler/thread_delegate_win.h b/base/profiler/thread_delegate_win.h index e4079e9..9e1d781 100644 --- a/base/profiler/thread_delegate_win.h +++ b/base/profiler/thread_delegate_win.h
@@ -47,11 +47,6 @@ std::vector<uintptr_t*> GetRegistersToRewrite( CONTEXT* thread_context) override; - UnwindResult WalkNativeFrames(CONTEXT* thread_context, - uintptr_t stack_top, - ModuleCache* module_cache, - std::vector<Frame>* stack) override; - private: win::ScopedHandle thread_handle_; const uintptr_t thread_stack_base_address_;
diff --git a/base/profiler/unwind_result.h b/base/profiler/unwind_result.h deleted file mode 100644 index 9aeaec8..0000000 --- a/base/profiler/unwind_result.h +++ /dev/null
@@ -1,25 +0,0 @@ -// 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 BASE_PROFILER_UNWIND_RESULT_H_ -#define BASE_PROFILER_UNWIND_RESULT_H_ - -namespace base { - -// The result of attempting to unwind stack frames. -enum class UnwindResult { - // The end of the stack was reached successfully. - COMPLETED, - - // The walk reached a frame that it doesn't know how to unwind, but might be - // unwindable by the other native/aux unwinder. - UNRECOGNIZED_FRAME, - - // The walk was aborted and is not resumable. - ABORTED, -}; - -} // namespace base - -#endif // BASE_PROFILER_UNWIND_RESULT_H_
diff --git a/base/profiler/unwinder.h b/base/profiler/unwinder.h index c42a391..09b3efa 100644 --- a/base/profiler/unwinder.h +++ b/base/profiler/unwinder.h
@@ -7,20 +7,32 @@ #include <vector> +#include "base/macros.h" #include "base/profiler/frame.h" #include "base/profiler/register_context.h" -#include "base/profiler/unwind_result.h" #include "base/sampling_heap_profiler/module_cache.h" namespace base { +// The result of attempting to unwind stack frames. +enum class UnwindResult { + // The end of the stack was reached successfully. + COMPLETED, + + // The walk reached a frame that it doesn't know how to unwind, but might be + // unwindable by the other native/aux unwinder. + UNRECOGNIZED_FRAME, + + // The walk was aborted and is not resumable. + ABORTED, +}; + // Unwinder provides an interface for stack frame unwinder implementations for // use with the StackSamplingProfiler. The profiler is expected to call // CanUnwind() to determine if the Unwinder thinks it can unwind from the frame // represented by the context values, then TryUnwind() to attempt the -// unwind. Implementations of CanUnwindFrom() and TryUnwind() should be -// stateless because stack samples for all target threads use the same Unwinder -// instance. +// unwind. Note that the stack samples for multiple collection scenarios are +// interleaved on a single Unwinder instance. class Unwinder { public: virtual ~Unwinder() = default; @@ -33,9 +45,11 @@ // doesn't have unwind information. virtual bool CanUnwindFrom(const Frame* current_frame) const = 0; - // Attempts to unwind the frame represented by the context values. If - // successful appends frames onto the stack and returns true. Otherwise - // returns false. + // Attempts to unwind the frame represented by the context values. + // Walks the native frames on the stack pointed to by the stack pointer in + // |thread_context|, appending the frames to |stack|. When invoked + // stack->back() contains the frame corresponding to the state in + // |thread_context|. virtual UnwindResult TryUnwind(RegisterContext* thread_context, uintptr_t stack_top, ModuleCache* module_cache,
diff --git a/base/supports_user_data.cc b/base/supports_user_data.cc index 2eb93f4..b3b21bb0 100644 --- a/base/supports_user_data.cc +++ b/base/supports_user_data.cc
@@ -6,6 +6,10 @@ namespace base { +std::unique_ptr<SupportsUserData::Data> SupportsUserData::Data::Clone() { + return nullptr; +} + SupportsUserData::SupportsUserData() { // Harmless to construct on a different execution sequence to subsequent // usage. @@ -27,7 +31,10 @@ DCHECK(sequence_checker_.CalledOnValidSequence()); // Avoid null keys; they are too vulnerable to collision. DCHECK(key); - user_data_[key] = std::move(data); + if (data.get()) + user_data_[key] = std::move(data); + else + RemoveUserData(key); } void SupportsUserData::RemoveUserData(const void* key) { @@ -39,6 +46,14 @@ sequence_checker_.DetachFromSequence(); } +void SupportsUserData::CloneDataFrom(const SupportsUserData& other) { + for (const auto& data_pair : other.user_data_) { + auto cloned_data = data_pair.second->Clone(); + if (cloned_data) + SetUserData(data_pair.first, std::move(cloned_data)); + } +} + SupportsUserData::~SupportsUserData() { DCHECK(sequence_checker_.CalledOnValidSequence() || user_data_.empty()); DataMap local_user_data;
diff --git a/base/supports_user_data.h b/base/supports_user_data.h index 1d14874..cb97a23 100644 --- a/base/supports_user_data.h +++ b/base/supports_user_data.h
@@ -27,17 +27,24 @@ class BASE_EXPORT Data { public: virtual ~Data() = default; + + // Returns a copy of |this|; null if copy is not supported. + virtual std::unique_ptr<Data> Clone(); }; // The user data allows the clients to associate data with this object. - // Multiple user data values can be stored under different keys. - // This object will TAKE OWNERSHIP of the given data pointer, and will - // delete the object if it is changed or the object is destroyed. // |key| must not be null--that value is too vulnerable for collision. + // NOTE: SetUserData() with an empty unique_ptr behaves the same as + // RemoveUserData(). Data* GetUserData(const void* key) const; void SetUserData(const void* key, std::unique_ptr<Data> data); void RemoveUserData(const void* key); + // Adds all data from |other|, that is clonable, to |this|. That is, this + // iterates over the data in |other|, and any data that returns non-null from + // Clone() is added to |this|. + void CloneDataFrom(const SupportsUserData& other); + // SupportsUserData is not thread-safe, and on debug build will assert it is // only used on one execution sequence. Calling this method allows the caller // to hand the SupportsUserData instance across execution sequences. Use only
diff --git a/base/task/task_scheduler/platform_native_worker_pool.cc b/base/task/task_scheduler/platform_native_worker_pool.cc index 243c413f..d32f278b 100644 --- a/base/task/task_scheduler/platform_native_worker_pool.cc +++ b/base/task/task_scheduler/platform_native_worker_pool.cc
@@ -54,7 +54,9 @@ #endif } -void PlatformNativeWorkerPool::Start() { +void PlatformNativeWorkerPool::Start(WorkerEnvironment worker_environment) { + worker_environment_ = worker_environment; + StartImpl(); ScopedWorkersExecutor executor(this);
diff --git a/base/task/task_scheduler/platform_native_worker_pool.h b/base/task/task_scheduler/platform_native_worker_pool.h index ca6a639..79e680a4 100644 --- a/base/task/task_scheduler/platform_native_worker_pool.h +++ b/base/task/task_scheduler/platform_native_worker_pool.h
@@ -20,7 +20,7 @@ ~PlatformNativeWorkerPool() override; // Starts the worker pool and allows tasks to begin running. - void Start(); + void Start(WorkerEnvironment worker_environment = WorkerEnvironment::NONE); // SchedulerWorkerPool: void JoinForTesting() override; @@ -40,6 +40,9 @@ virtual void StartImpl() = 0; virtual void SubmitWork() = 0; + // Used to control the worker environment. Supports COM MTA on Windows. + WorkerEnvironment worker_environment_ = WorkerEnvironment::NONE; + private: class ScopedWorkersExecutor;
diff --git a/base/task/task_scheduler/platform_native_worker_pool_win.cc b/base/task/task_scheduler/platform_native_worker_pool_win.cc index 4178f33109..1a85e06 100644 --- a/base/task/task_scheduler/platform_native_worker_pool_win.cc +++ b/base/task/task_scheduler/platform_native_worker_pool_win.cc
@@ -4,11 +4,26 @@ #include "base/task/task_scheduler/platform_native_worker_pool_win.h" +#include "base/no_destructor.h" #include "base/task/task_scheduler/task_tracker.h" +#include "base/threading/thread_local.h" +#include "base/win/scoped_com_initializer.h" namespace base { namespace internal { +namespace { + +// Used to enable COM MTA when creating threads via the Windows Thread Pool API. +ThreadLocalOwnedPointer<win::ScopedCOMInitializer>& +ScopedCOMInitializerForCurrentThread() { + static base::NoDestructor<ThreadLocalOwnedPointer<win::ScopedCOMInitializer>> + scoped_com_initializer; + return *scoped_com_initializer; +} + +} // namespace + PlatformNativeWorkerPoolWin::PlatformNativeWorkerPoolWin( TrackedRef<TaskTracker> task_tracker, TrackedRef<Delegate> delegate, @@ -53,6 +68,14 @@ PTP_WORK) { auto* worker_pool = static_cast<PlatformNativeWorkerPoolWin*>( scheduler_worker_pool_windows_impl); + + if (worker_pool->worker_environment_ == WorkerEnvironment::COM_MTA && + !ScopedCOMInitializerForCurrentThread().Get()) { + ScopedCOMInitializerForCurrentThread().Set( + std::make_unique<win::ScopedCOMInitializer>( + win::ScopedCOMInitializer::kMTA)); + } + worker_pool->RunNextSequenceImpl(); }
diff --git a/base/task/task_scheduler/scheduler_worker_pool.h b/base/task/task_scheduler/scheduler_worker_pool.h index bb6cf27..9c14fe3 100644 --- a/base/task/task_scheduler/scheduler_worker_pool.h +++ b/base/task/task_scheduler/scheduler_worker_pool.h
@@ -13,6 +13,7 @@ #include "base/task/task_scheduler/sequence.h" #include "base/task/task_scheduler/task.h" #include "base/task/task_scheduler/tracked_ref.h" +#include "build/build_config.h" namespace base { namespace internal { @@ -34,6 +35,15 @@ const TaskTraits& traits) = 0; }; + enum class WorkerEnvironment { + // No special worker environment required. + NONE, +#if defined(OS_WIN) + // Initialize a COM MTA on the worker. + COM_MTA, +#endif // defined(OS_WIN) + }; + ~SchedulerWorkerPool() override; // CanScheduleSequenceObserver:
diff --git a/base/task/task_scheduler/scheduler_worker_pool_impl.cc b/base/task/task_scheduler/scheduler_worker_pool_impl.cc index 280d9b86..1effafe 100644 --- a/base/task/task_scheduler/scheduler_worker_pool_impl.cc +++ b/base/task/task_scheduler/scheduler_worker_pool_impl.cc
@@ -31,6 +31,7 @@ #include "base/threading/scoped_blocking_call.h" #include "base/threading/thread_checker.h" #include "base/threading/thread_restrictions.h" +#include "build/build_config.h" #if defined(OS_WIN) #include "base/win/scoped_com_initializer.h"
diff --git a/base/task/task_scheduler/scheduler_worker_pool_impl.h b/base/task/task_scheduler/scheduler_worker_pool_impl.h index 96d5e21..6949e51 100644 --- a/base/task/task_scheduler/scheduler_worker_pool_impl.h +++ b/base/task/task_scheduler/scheduler_worker_pool_impl.h
@@ -31,7 +31,6 @@ #include "base/task/task_scheduler/tracked_ref.h" #include "base/task_runner.h" #include "base/time/time.h" -#include "build/build_config.h" namespace base { @@ -51,15 +50,6 @@ // This class is thread-safe. class BASE_EXPORT SchedulerWorkerPoolImpl : public SchedulerWorkerPool { public: - enum class WorkerEnvironment { - // No special worker environment required. - NONE, -#if defined(OS_WIN) - // Initialize a COM MTA on the worker. - COM_MTA, -#endif // defined(OS_WIN) - }; - // Constructs a pool without workers. // // |histogram_label| is used to label the pool's histograms ("TaskScheduler."
diff --git a/base/task/task_scheduler/scheduler_worker_pool_impl_unittest.cc b/base/task/task_scheduler/scheduler_worker_pool_impl_unittest.cc index 9e55160fc..d3afa74 100644 --- a/base/task/task_scheduler/scheduler_worker_pool_impl_unittest.cc +++ b/base/task/task_scheduler/scheduler_worker_pool_impl_unittest.cc
@@ -55,10 +55,6 @@ #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" -#if defined(OS_WIN) -#include "base/win/com_init_util.h" -#endif // defined(OS_WIN) - namespace base { namespace internal { namespace { @@ -110,7 +106,7 @@ SchedulerWorkerPoolParams(max_tasks, suggested_reclaim_time), max_best_effort_tasks ? max_best_effort_tasks.value() : max_tasks, service_thread_.task_runner(), worker_observer, - SchedulerWorkerPoolImpl::WorkerEnvironment::NONE, may_block_threshold); + SchedulerWorkerPool::WorkerEnvironment::NONE, may_block_threshold); } void CreateAndStartWorkerPool( @@ -301,28 +297,6 @@ worker_pool_->WaitForAllWorkersIdleForTesting(); } -#if defined(OS_WIN) -TEST_P(TaskSchedulerWorkerPoolImplTestParam, NoEnvironment) { - // Verify that COM is not initialized in a SchedulerWorkerPoolImpl initialized - // with SchedulerWorkerPoolImpl::WorkerEnvironment::NONE. - scoped_refptr<TaskRunner> task_runner = CreateTaskRunnerWithExecutionMode( - GetParam(), &mock_scheduler_task_runner_delegate_); - - WaitableEvent task_running; - task_runner->PostTask( - FROM_HERE, BindOnce( - [](WaitableEvent* task_running) { - win::AssertComApartmentType(win::ComApartmentType::NONE); - task_running->Signal(); - }, - &task_running)); - - task_running.Wait(); - - worker_pool_->WaitForAllWorkersIdleForTesting(); -} -#endif // defined(OS_WIN) - INSTANTIATE_TEST_SUITE_P(Parallel, TaskSchedulerWorkerPoolImplTestParam, ::testing::Values(test::ExecutionMode::PARALLEL)); @@ -330,62 +304,6 @@ TaskSchedulerWorkerPoolImplTestParam, ::testing::Values(test::ExecutionMode::SEQUENCED)); -#if defined(OS_WIN) - -namespace { - -class TaskSchedulerWorkerPoolImplTestCOMMTAParam - : public TaskSchedulerWorkerPoolImplTestBase, - public testing::TestWithParam<test::ExecutionMode> { - protected: - TaskSchedulerWorkerPoolImplTestCOMMTAParam() = default; - - void SetUp() override { - CreateWorkerPool(); - ASSERT_TRUE(worker_pool_); - worker_pool_->Start(SchedulerWorkerPoolParams(kMaxTasks, TimeDelta::Max()), - kMaxTasks, service_thread_.task_runner(), nullptr, - SchedulerWorkerPoolImpl::WorkerEnvironment::COM_MTA); - } - - void TearDown() override { - TaskSchedulerWorkerPoolImplTestBase::CommonTearDown(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplTestCOMMTAParam); -}; - -} // namespace - -TEST_P(TaskSchedulerWorkerPoolImplTestCOMMTAParam, COMMTAInitialized) { - // Verify that SchedulerWorkerPoolImpl workers have a COM MTA available. - scoped_refptr<TaskRunner> task_runner = CreateTaskRunnerWithExecutionMode( - GetParam(), &mock_scheduler_task_runner_delegate_); - - WaitableEvent task_running; - task_runner->PostTask( - FROM_HERE, BindOnce( - [](WaitableEvent* task_running) { - win::AssertComApartmentType(win::ComApartmentType::MTA); - task_running->Signal(); - }, - &task_running)); - - task_running.Wait(); - - worker_pool_->WaitForAllWorkersIdleForTesting(); -} - -INSTANTIATE_TEST_SUITE_P(Parallel, - TaskSchedulerWorkerPoolImplTestCOMMTAParam, - ::testing::Values(test::ExecutionMode::PARALLEL)); -INSTANTIATE_TEST_SUITE_P(Sequenced, - TaskSchedulerWorkerPoolImplTestCOMMTAParam, - ::testing::Values(test::ExecutionMode::SEQUENCED)); - -#endif // defined(OS_WIN) - namespace { class TaskSchedulerWorkerPoolImplStartInBodyTest @@ -1751,7 +1669,7 @@ worker_pool_->Start( SchedulerWorkerPoolParams(kMaxTasks, base::TimeDelta::Max()), kMaxBestEffortTasks, service_thread_.task_runner(), nullptr, - SchedulerWorkerPoolImpl::WorkerEnvironment::NONE); + SchedulerWorkerPool::WorkerEnvironment::NONE); } void TearDown() override { @@ -1841,7 +1759,7 @@ worker_pool_->Start( SchedulerWorkerPoolParams(kLocalMaxTasks, kReclaimTimeForRacyCleanupTest), kLocalMaxTasks, service_thread_.task_runner(), nullptr, - SchedulerWorkerPoolImpl::WorkerEnvironment::NONE); + SchedulerWorkerPool::WorkerEnvironment::NONE); scoped_refptr<TaskRunner> task_runner = test::CreateTaskRunnerWithTraits( {WithBaseSyncPrimitives()}, &mock_scheduler_task_runner_delegate_);
diff --git a/base/task/task_scheduler/scheduler_worker_pool_unittest.cc b/base/task/task_scheduler/scheduler_worker_pool_unittest.cc index 14f7a504..c3b236c 100644 --- a/base/task/task_scheduler/scheduler_worker_pool_unittest.cc +++ b/base/task/task_scheduler/scheduler_worker_pool_unittest.cc
@@ -32,6 +32,7 @@ #if defined(OS_WIN) #include "base/task/task_scheduler/platform_native_worker_pool_win.h" +#include "base/win/com_init_util.h" #elif defined(OS_MACOSX) #include "base/task/task_scheduler/platform_native_worker_pool_mac.h" #endif @@ -140,7 +141,9 @@ mock_scheduler_task_runner_delegate_.SetWorkerPool(worker_pool_.get()); } - void StartWorkerPool() { + void StartWorkerPool( + SchedulerWorkerPool::WorkerEnvironment worker_environment = + SchedulerWorkerPool::WorkerEnvironment::NONE) { ASSERT_TRUE(worker_pool_); switch (GetParam().pool_type) { case test::PoolType::GENERIC: { @@ -149,14 +152,14 @@ scheduler_worker_pool_impl->Start( SchedulerWorkerPoolParams(kMaxTasks, TimeDelta::Max()), kMaxBestEffortTasks, service_thread_.task_runner(), nullptr, - SchedulerWorkerPoolImpl::WorkerEnvironment::NONE); + worker_environment); break; } #if defined(OS_WIN) || defined(OS_MACOSX) case test::PoolType::NATIVE: { PlatformNativeWorkerPoolType* scheduler_worker_pool_native_impl = static_cast<PlatformNativeWorkerPoolType*>(worker_pool_.get()); - scheduler_worker_pool_native_impl->Start(); + scheduler_worker_pool_native_impl->Start(worker_environment); break; } #endif @@ -404,6 +407,40 @@ task_tracker_.FlushForTesting(); } +#if defined(OS_WIN) +TEST_P(TaskSchedulerWorkerPoolTest, COMMTAWorkerEnvironment) { + StartWorkerPool(SchedulerWorkerPool::WorkerEnvironment::COM_MTA); + auto task_runner = test::CreateTaskRunnerWithExecutionMode( + GetParam().execution_mode, &mock_scheduler_task_runner_delegate_); + + WaitableEvent task_ran; + task_runner->PostTask( + FROM_HERE, BindOnce( + [](WaitableEvent* task_ran) { + win::AssertComApartmentType(win::ComApartmentType::MTA); + task_ran->Signal(); + }, + Unretained(&task_ran))); + task_ran.Wait(); +} + +TEST_P(TaskSchedulerWorkerPoolTest, NoWorkerEnvironment) { + StartWorkerPool(SchedulerWorkerPool::WorkerEnvironment::NONE); + auto task_runner = test::CreateTaskRunnerWithExecutionMode( + GetParam().execution_mode, &mock_scheduler_task_runner_delegate_); + + WaitableEvent task_ran; + task_runner->PostTask( + FROM_HERE, BindOnce( + [](WaitableEvent* task_ran) { + win::AssertComApartmentType(win::ComApartmentType::NONE); + task_ran->Signal(); + }, + Unretained(&task_ran))); + task_ran.Wait(); +} +#endif + INSTANTIATE_TEST_SUITE_P(GenericParallel, TaskSchedulerWorkerPoolTest, ::testing::Values(PoolExecutionType{
diff --git a/base/task/task_scheduler/task_scheduler_impl.cc b/base/task/task_scheduler/task_scheduler_impl.cc index 3366fbf5..7acd6f68 100644 --- a/base/task/task_scheduler/task_scheduler_impl.cc +++ b/base/task/task_scheduler/task_scheduler_impl.cc
@@ -134,19 +134,19 @@ single_thread_task_runner_manager_.Start(scheduler_worker_observer); - const SchedulerWorkerPoolImpl::WorkerEnvironment worker_environment = + const SchedulerWorkerPool::WorkerEnvironment worker_environment = #if defined(OS_WIN) init_params.shared_worker_pool_environment == InitParams::SharedWorkerPoolEnvironment::COM_MTA - ? SchedulerWorkerPoolImpl::WorkerEnvironment::COM_MTA - : SchedulerWorkerPoolImpl::WorkerEnvironment::NONE; + ? SchedulerWorkerPool::WorkerEnvironment::COM_MTA + : SchedulerWorkerPool::WorkerEnvironment::NONE; #else - SchedulerWorkerPoolImpl::WorkerEnvironment::NONE; + SchedulerWorkerPool::WorkerEnvironment::NONE; #endif #if defined(OS_WIN) || defined(OS_MACOSX) if (native_foreground_pool_) { - native_foreground_pool_->Start(); + native_foreground_pool_->Start(worker_environment); } else #endif {
diff --git a/base/util/README.md b/base/util/README.md index dc224b10..bd3f8199 100644 --- a/base/util/README.md +++ b/base/util/README.md
@@ -78,12 +78,15 @@ ## How does this differ from //components -First, //base/util is a layer lower than //components so some code just cannot fit -in components. +Both //components and //base/util contain subdirectories that are (a) intended +for reuse. In addition, //components imposes no global layering in Chromium, so +a subdirectory placed in //components can be used from most-to-all layers in the +codebase, subject to the dependencies that that subdirectory itself holds. -Second, //components contains things are closer to full features or subsystems -(eg autofill, heap profiler, cloud devices, visited link tracker) that are not -really intended for large scale reuse. +In spite of these similarities, there are *conceptual* differences: //components +contains things are closer to full features or subsystems (eg autofill, heap +profiler, cloud devices, visited link tracker) that are not really intended for +large scale reuse. There is some overlap and at some point it will become a judgment call, but in general, //components are a better fit if the code in question is a feature,
diff --git a/build/android/apk_operations.py b/build/android/apk_operations.py index 2f6b204..55e3e88 100755 --- a/build/android/apk_operations.py +++ b/build/android/apk_operations.py
@@ -263,6 +263,24 @@ device_utils.DeviceUtils.parallel(devices).pMap(uninstall) +def _IsWebViewProvider(apk_helper_instance): + meta_data = apk_helper_instance.GetAllMetadata() + meta_data_keys = [pair[0] for pair in meta_data] + return 'com.android.webview.WebViewLibrary' in meta_data_keys + + +def _SetWebViewProvider(devices, package_name): + + def switch_provider(device): + if device.build_version_sdk < version_codes.NOUGAT: + logging.error('No need to switch provider on pre-Nougat devices (%s)', + device.serial) + else: + device.SetWebViewImplementation(package_name) + + device_utils.DeviceUtils.parallel(devices).pMap(switch_provider) + + def _NormalizeProcessName(debug_process_name, package_name): if not debug_process_name: debug_process_name = package_name @@ -1155,6 +1173,24 @@ _UninstallApk(self.devices, self.install_dict, self.args.package_name) +class _SetWebViewProviderCommand(_Command): + name = 'set-webview-provider' + description = ("Sets the device's WebView provider to this APK's " + "package name.") + needs_package_name = True + + def Run(self): + if self.is_bundle: + # TODO(ntfschr): Support this by figuring out how to construct + # self.apk_helper for bundles. + raise Exception( + 'Switching WebView providers not supported for bundles yet!') + if not _IsWebViewProvider(self.apk_helper): + raise Exception('This package does not have a WebViewLibrary meta-data ' + 'tag. Are you sure it contains a WebView implementation?') + _SetWebViewProvider(self.devices, self.args.package_name) + + class _LaunchCommand(_Command): name = 'launch' description = ('Sends a launch intent for the APK or bundle after first ' @@ -1496,6 +1532,7 @@ _DevicesCommand, _InstallCommand, _UninstallCommand, + _SetWebViewProviderCommand, _LaunchCommand, _StopCommand, _ClearDataCommand,
diff --git a/build/config/android/config.gni b/build/config/android/config.gni index e5a6e3c..a4e230c7 100644 --- a/build/config/android/config.gni +++ b/build/config/android/config.gni
@@ -226,9 +226,6 @@ # Checks that proguard flags have not changed (!is_java_debug only). check_android_configuration = false - # Enables instantiation of 64-bit browser targets. - enable_64_bit_browser = true - # Enable the chrome build for devices without touchscreens. notouch_build = false
diff --git a/cc/layers/layer_sticky_position_constraint.cc b/cc/layers/layer_sticky_position_constraint.cc index 718d567a..4da9089 100644 --- a/cc/layers/layer_sticky_position_constraint.cc +++ b/cc/layers/layer_sticky_position_constraint.cc
@@ -17,9 +17,7 @@ left_offset(0.f), right_offset(0.f), top_offset(0.f), - bottom_offset(0.f), - nearest_element_shifting_sticky_box(kInvalidElementId), - nearest_element_shifting_containing_block(kInvalidElementId) {} + bottom_offset(0.f) {} LayerStickyPositionConstraint::LayerStickyPositionConstraint( const LayerStickyPositionConstraint& other) = default;
diff --git a/cc/layers/viewport.cc b/cc/layers/viewport.cc index b99cee3..d58b9f0 100644 --- a/cc/layers/viewport.cc +++ b/cc/layers/viewport.cc
@@ -49,21 +49,20 @@ gfx::Vector2dF pending_content_delta = content_delta; - ScrollNode* inner_node = InnerScrollNode(); + // Attempt to scroll inner viewport first. pending_content_delta -= host_impl_->ScrollSingleNode( - inner_node, pending_content_delta, viewport_point, is_direct_manipulation, - &scroll_tree()); + InnerScrollNode(), pending_content_delta, viewport_point, + is_direct_manipulation, &scroll_tree()); - ScrollResult result; - + // Now attempt to scroll the outer viewport. if (scroll_outer_viewport) { pending_content_delta -= host_impl_->ScrollSingleNode( OuterScrollNode(), pending_content_delta, viewport_point, is_direct_manipulation, &scroll_tree()); } + ScrollResult result; result.consumed_delta = delta - AdjustOverscroll(pending_content_delta); - result.content_scrolled_delta = content_delta - pending_content_delta; return result; }
diff --git a/cc/layers/viewport.h b/cc/layers/viewport.h index 5abe67d..0343ff0 100644 --- a/cc/layers/viewport.h +++ b/cc/layers/viewport.h
@@ -55,9 +55,7 @@ bool CanScroll(const ScrollState& scroll_state) const; - // Scrolls the viewport. Unlike the above method, scrolls the inner before - // the outer viewport. Doesn't affect browser controls or return a result - // since callers don't need it. + // TODO(bokan): Callers can now be replaced by ScrollBy. void ScrollByInnerFirst(const gfx::Vector2dF& delta); // Scrolls the viewport, bubbling the delta between the inner and outer
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc index 96b32a6..eaff9df 100644 --- a/cc/tiles/gpu_image_decode_cache.cc +++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -1513,6 +1513,15 @@ RemoveFromPersistentCache(found_persistent); } + // Don't keep discardable cpu memory for GPU backed images. The cache hit rate + // of the cpu fallback (in case we don't find this image in gpu memory) is + // too low to cache this data. + if (image_data->decode.ref_count == 0 && + image_data->mode != DecodedDataMode::kCpu && + image_data->HasUploadedData()) { + image_data->decode.ResetData(); + } + // If we have no refs on an uploaded image, it should be unlocked. Do this // before any attempts to delete the image. if (image_data->IsGpuOrTransferCache() && image_data->upload.ref_count == 0 &&
diff --git a/cc/tiles/gpu_image_decode_cache_unittest.cc b/cc/tiles/gpu_image_decode_cache_unittest.cc index e8418bf..087f8b2 100644 --- a/cc/tiles/gpu_image_decode_cache_unittest.cc +++ b/cc/tiles/gpu_image_decode_cache_unittest.cc
@@ -2429,12 +2429,6 @@ EXPECT_TRUE(decoded_draw_image.image()); EXPECT_TRUE(decoded_draw_image.is_budgeted()); cache->DrawWithImageFinished(draw_image, decoded_draw_image); - // For non-lazy images which are downscaled, the scaled image should be - // cached. - auto sw_image = cache->GetSWImageDecodeForTesting(draw_image); - EXPECT_TRUE(sw_image); - EXPECT_EQ(sw_image->width(), (GetNormalImageSize().width() + 1) / 2); - EXPECT_EQ(sw_image->height(), (GetNormalImageSize().height() + 1) / 2); } TEST_P(GpuImageDecodeCacheTest, KeepOnlyLast2ContentIds) {
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc index ec3f35f..e32fa24 100644 --- a/cc/trees/draw_property_utils.cc +++ b/cc/trees/draw_property_utils.cc
@@ -708,14 +708,12 @@ DCHECK(to_target.Preserves2dAxisAlignment()); - const gfx::Vector2dF& translate = to_target.To2dTranslation(); - const gfx::Vector2dF& scale = to_target.Scale2d(); - - gfx::RRectF bounds = node->rounded_corner_bounds; - bounds.Scale(scale.x(), scale.y()); - bounds.Offset(translate); - - return std::make_pair(bounds, node->is_fast_rounded_corner); + SkRRect result; + if (!SkRRect(node->rounded_corner_bounds) + .transform(to_target.matrix(), &result)) { + return kEmptyRoundedCornerInfo; + } + return std::make_pair(gfx::RRectF(result), node->is_fast_rounded_corner); } static void UpdateRenderTarget(EffectTree* effect_tree) {
diff --git a/cc/trees/element_id.cc b/cc/trees/element_id.cc index b460a2e..6690378 100644 --- a/cc/trees/element_id.cc +++ b/cc/trees/element_id.cc
@@ -14,6 +14,8 @@ namespace cc { +const ElementIdType ElementId::kInvalidElementId = 0; + ElementId LayerIdToElementIdForTesting(int layer_id) { return ElementId(std::numeric_limits<int>::max() - layer_id); }
diff --git a/cc/trees/element_id.h b/cc/trees/element_id.h index b34782d9..e8275c5 100644 --- a/cc/trees/element_id.h +++ b/cc/trees/element_id.h
@@ -26,8 +26,6 @@ using ElementIdType = uint64_t; -static const ElementIdType kInvalidElementId = 0; - // Element ids are chosen by cc's clients and can be used as a stable identifier // across updates. // @@ -47,14 +45,17 @@ // targets. A Layer's element id can change over the Layer's lifetime because // non-default ElementIds are only set during an animation's lifetime. struct CC_EXPORT ElementId { - explicit ElementId(ElementIdType id) : id_(id) {} - ElementId() : ElementId(kInvalidElementId) {} + explicit ElementId(ElementIdType id) : id_(id) { + DCHECK_NE(id, kInvalidElementId); + } + + ElementId() : id_(kInvalidElementId) {} bool operator==(const ElementId& o) const { return id_ == o.id_; } bool operator!=(const ElementId& o) const { return !(*this == o); } bool operator<(const ElementId& o) const { return id_ < o.id_; } - // An ElementId's conversion to a boolean value depends only on its primaryId. + // Returns true if the ElementId has been initialized with a valid id. explicit operator bool() const { return !!id_; } void AddToTracedValue(base::trace_event::TracedValue* res) const; @@ -66,6 +67,7 @@ private: friend struct ElementIdHash; + static const ElementIdType kInvalidElementId; // The compositor treats this as an opaque handle and should not know how to // interpret these bits. Non-blink cc clients typically operate in terms of
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 0dc635ae..89ae622 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -4578,7 +4578,15 @@ TRACE_EVENT2("cc", "LayerTreeHostImpl::SetSynchronousInputHandlerRootScrollOffset", "offset_x", root_offset.x(), "offset_y", root_offset.y()); - bool changed = active_tree_->DistributeRootScrollOffset(root_offset); + + gfx::Vector2dF delta = root_offset.DeltaFrom(viewport()->TotalScrollOffset()); + bool changed = !viewport() + ->ScrollBy(delta, + /*viewport_point=*/gfx::Point(), + /*is_wheel_scroll=*/false, + /*affect_browser_controls=*/false, + /*scroll_outer_viewport=*/true) + .consumed_delta.IsZero(); if (!changed) return; @@ -4965,7 +4973,7 @@ if (!browser_controls_offset_manager_->has_animation()) return false; - gfx::Vector2dF scroll = browser_controls_offset_manager_->Animate(time); + gfx::Vector2dF scroll_delta = browser_controls_offset_manager_->Animate(time); if (browser_controls_offset_manager_->has_animation()) SetNeedsOneBeginImplFrame(); @@ -4973,11 +4981,15 @@ if (active_tree_->TotalScrollOffset().y() == 0.f) return false; - if (scroll.IsZero()) + if (scroll_delta.IsZero()) return false; DCHECK(viewport()); - viewport()->ScrollBy(scroll, gfx::Point(), false, false, true); + viewport()->ScrollBy(scroll_delta, + /*viewport_point=*/gfx::Point(), + /*is_wheel_scroll=*/false, + /*affect_browser_controls=*/false, + /*scroll_outer_viewport=*/true); client_->SetNeedsCommitOnImplThread(); client_->RenewTreePriority(); return true;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index a24b83e..74da659 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -7703,42 +7703,121 @@ gfx::ScrollOffsetToVector2dF(scroll_offset)); } -TEST_F(LayerTreeHostImplTest, - ExternalRootLayerScrollOffsetPreventedByUserNotScrollable) { - host_impl_->active_tree()->SetDeviceViewportSize(gfx::Size(10, 20)); - LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100)); - LayerImpl* clip_layer = - scroll_layer->test_properties()->parent->test_properties()->parent; - clip_layer->SetBounds(gfx::Size(10, 20)); - scroll_layer->SetScrollable(gfx::Size(10, 20)); - scroll_layer->SetDrawsContent(true); - host_impl_->active_tree() - ->InnerViewportScrollLayer() - ->test_properties() - ->user_scrollable_vertical = false; - host_impl_->active_tree() - ->InnerViewportScrollLayer() - ->test_properties() - ->user_scrollable_horizontal = false; - host_impl_->active_tree()->BuildPropertyTreesForTesting(); +// Ensure that the SetSynchronousInputHandlerRootScrollOffset method used by +// the WebView API correctly respects the user_scrollable bits on both of the +// inner and outer viewport scroll nodes. +TEST_F(LayerTreeHostImplTest, SetRootScrollOffsetUserScrollable) { + gfx::Size viewport_size(100, 100); + gfx::Size content_size(200, 200); + CreateBasicVirtualViewportLayers(viewport_size, content_size); - // Draw first frame to clear any pending draws and check scroll. + auto* outer_scroll = host_impl_->active_tree()->OuterViewportScrollLayer(); + auto* inner_scroll = host_impl_->active_tree()->InnerViewportScrollLayer(); + + ScrollTree& scroll_tree = + host_impl_->active_tree()->property_trees()->scroll_tree; + ElementId inner_element_id = inner_scroll->element_id(); + ElementId outer_element_id = outer_scroll->element_id(); + + host_impl_->active_tree()->BuildPropertyTreesForTesting(); DrawFrame(); - CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f)); - EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties()); - // Set external scroll delta on delegate and notify LayerTreeHost. - gfx::ScrollOffset scroll_offset(10.f, 10.f); - host_impl_->SetSynchronousInputHandlerRootScrollOffset(scroll_offset); - host_impl_->active_tree()->BuildPropertyTreesForTesting(); + float page_scale_factor = 2.f; + host_impl_->active_tree()->PushPageScaleFromMainThread( + page_scale_factor, page_scale_factor, page_scale_factor); - TestFrameData frame; - EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame)); - host_impl_->DrawLayers(&frame); - host_impl_->DidDrawAllLayers(frame); - EXPECT_TRUE(frame.has_no_damage); - CheckLayerScrollDelta(scroll_layer, - gfx::ScrollOffsetToVector2dF(gfx::ScrollOffset())); + // Disable scrolling the inner viewport. Only the outer should scroll. + { + ASSERT_FALSE(did_request_redraw_); + inner_scroll->test_properties()->user_scrollable_vertical = false; + inner_scroll->test_properties()->user_scrollable_horizontal = false; + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + gfx::ScrollOffset scroll_offset(25.f, 30.f); + host_impl_->SetSynchronousInputHandlerRootScrollOffset(scroll_offset); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(), + scroll_tree.current_scroll_offset(inner_element_id)); + scroll_offset.Scale(1.f / page_scale_factor); + EXPECT_VECTOR_EQ(scroll_offset, + scroll_tree.current_scroll_offset(outer_element_id)); + EXPECT_TRUE(did_request_redraw_); + + // Reset + did_request_redraw_ = false; + inner_scroll->test_properties()->user_scrollable_vertical = true; + inner_scroll->test_properties()->user_scrollable_horizontal = true; + outer_scroll->SetCurrentScrollOffset(gfx::ScrollOffset(0, 0)); + } + + // Disable scrolling the outer viewport. The inner should scroll to its + // extent but there should be no bubbling over to the outer viewport. + { + ASSERT_FALSE(did_request_redraw_); + outer_scroll->test_properties()->user_scrollable_vertical = false; + outer_scroll->test_properties()->user_scrollable_horizontal = false; + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + gfx::ScrollOffset scroll_offset(120.f, 140.f); + host_impl_->SetSynchronousInputHandlerRootScrollOffset(scroll_offset); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(50.f, 50.f), + scroll_tree.current_scroll_offset(inner_element_id)); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(), + scroll_tree.current_scroll_offset(outer_element_id)); + EXPECT_TRUE(did_request_redraw_); + + // Reset + did_request_redraw_ = false; + inner_scroll->test_properties()->user_scrollable_vertical = true; + inner_scroll->test_properties()->user_scrollable_horizontal = true; + inner_scroll->SetCurrentScrollOffset(gfx::ScrollOffset(0, 0)); + } + + // Disable both viewports. No scrolling should take place, no redraw should + // be requested. + { + ASSERT_FALSE(did_request_redraw_); + outer_scroll->test_properties()->user_scrollable_vertical = false; + outer_scroll->test_properties()->user_scrollable_horizontal = false; + inner_scroll->test_properties()->user_scrollable_vertical = false; + inner_scroll->test_properties()->user_scrollable_horizontal = false; + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + gfx::ScrollOffset scroll_offset(60.f, 70.f); + host_impl_->SetSynchronousInputHandlerRootScrollOffset(scroll_offset); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(), + scroll_tree.current_scroll_offset(inner_element_id)); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(), + scroll_tree.current_scroll_offset(outer_element_id)); + EXPECT_FALSE(did_request_redraw_); + + // Reset + inner_scroll->test_properties()->user_scrollable_vertical = true; + inner_scroll->test_properties()->user_scrollable_horizontal = true; + outer_scroll->test_properties()->user_scrollable_vertical = true; + outer_scroll->test_properties()->user_scrollable_horizontal = true; + } + + // If the inner is at its extent but the outer cannot scroll, we shouldn't + // request a redraw. + { + ASSERT_FALSE(did_request_redraw_); + outer_scroll->test_properties()->user_scrollable_vertical = false; + outer_scroll->test_properties()->user_scrollable_horizontal = false; + inner_scroll->SetCurrentScrollOffset(gfx::ScrollOffset(50.f, 50.f)); + host_impl_->active_tree()->BuildPropertyTreesForTesting(); + + gfx::ScrollOffset scroll_offset(60.f, 70.f); + host_impl_->SetSynchronousInputHandlerRootScrollOffset(scroll_offset); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(50.f, 50.f), + scroll_tree.current_scroll_offset(inner_element_id)); + EXPECT_VECTOR_EQ(gfx::ScrollOffset(), + scroll_tree.current_scroll_offset(outer_element_id)); + EXPECT_FALSE(did_request_redraw_); + + // Reset + outer_scroll->test_properties()->user_scrollable_vertical = true; + outer_scroll->test_properties()->user_scrollable_horizontal = true; + } } TEST_F(LayerTreeHostImplTest, OverscrollRoot) { @@ -11246,7 +11325,7 @@ } }; -TEST_F(LayerTreeHostImplVirtualViewportTest, ScrollBothInnerAndOuterLayer) { +TEST_F(LayerTreeHostImplVirtualViewportTest, RootScrollBothInnerAndOuterLayer) { gfx::Size content_size = gfx::Size(100, 160); gfx::Size outer_viewport = gfx::Size(50, 80); gfx::Size inner_viewport = gfx::Size(25, 40); @@ -11269,11 +11348,11 @@ EXPECT_EQ(gfx::ScrollOffset(25.f, 40.f), inner_scroll->MaxScrollOffset()); EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f), outer_scroll->MaxScrollOffset()); - // Outer viewport scrolls first. Then the rest is applied to the inner + // Inner viewport scrolls first. Then the rest is applied to the outer // viewport. - EXPECT_EQ(gfx::ScrollOffset(20.f, 20.f), + EXPECT_EQ(gfx::ScrollOffset(25.f, 40.f), inner_scroll->CurrentScrollOffset()); - EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f), + EXPECT_EQ(gfx::ScrollOffset(45.f, 60.f), outer_scroll->CurrentScrollOffset()); } }
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 8a8fc92..76d41d91 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -1740,49 +1740,6 @@ state->EndArray(); } -bool LayerTreeImpl::DistributeRootScrollOffset( - const gfx::ScrollOffset& desired_root_offset) { - if (!InnerViewportScrollNode() || !OuterViewportScrollLayer()) - return false; - - gfx::ScrollOffset root_offset = desired_root_offset; - ScrollTree& scroll_tree = property_trees()->scroll_tree; - - // If we get here, we have both inner/outer viewports, and need to distribute - // the scroll offset between them. - gfx::ScrollOffset inner_viewport_offset = - scroll_tree.current_scroll_offset(InnerViewportScrollNode()->element_id); - gfx::ScrollOffset outer_viewport_offset = - OuterViewportScrollLayer()->CurrentScrollOffset(); - DCHECK(inner_viewport_offset + outer_viewport_offset == TotalScrollOffset()); - - // Setting the root scroll offset is driven by user actions so prevent - // it if it is not user scrollable in certain directions. - if (!InnerViewportScrollNode()->user_scrollable_horizontal) - root_offset.set_x(inner_viewport_offset.x() + outer_viewport_offset.x()); - - if (!InnerViewportScrollNode()->user_scrollable_vertical) - root_offset.set_y(inner_viewport_offset.y() + outer_viewport_offset.y()); - - // It may be nothing has changed. - if (inner_viewport_offset + outer_viewport_offset == root_offset) - return false; - - gfx::ScrollOffset max_outer_viewport_scroll_offset = - OuterViewportScrollLayer()->MaxScrollOffset(); - - outer_viewport_offset = root_offset - inner_viewport_offset; - outer_viewport_offset.SetToMin(max_outer_viewport_scroll_offset); - outer_viewport_offset.SetToMax(gfx::ScrollOffset()); - - OuterViewportScrollLayer()->SetCurrentScrollOffset(outer_viewport_offset); - inner_viewport_offset = root_offset - outer_viewport_offset; - if (scroll_tree.SetScrollOffset(InnerViewportScrollNode()->element_id, - inner_viewport_offset)) - DidUpdateScrollOffset(InnerViewportScrollNode()->element_id); - return true; -} - void LayerTreeImpl::QueueSwapPromise( std::unique_ptr<SwapPromise> swap_promise) { DCHECK(swap_promise);
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index 5d1097b..88d798bc 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h
@@ -491,10 +491,6 @@ // Used for accessing the task runner and debug assertions. TaskRunnerProvider* task_runner_provider() const; - // Distribute the root scroll between outer and inner viewport scroll layer. - // The outer viewport scroll layer scrolls first. - bool DistributeRootScrollOffset(const gfx::ScrollOffset& root_offset); - void ApplyScroll(ScrollNode* scroll_node, ScrollState* scroll_state) { host_impl_->ApplyScroll(scroll_node, scroll_state); }
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 103dada..2ea2c0e 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -1432,7 +1432,7 @@ is_bundle = true } - if (android_64bit_target_cpu && enable_64_bit_browser) { + if (android_64bit_target_cpu) { group("monochrome_64_secondary_abi_lib") { public_deps = [ ":monochrome_64($android_secondary_abi_toolchain)", @@ -1446,13 +1446,11 @@ } } else { # 64-bit browser library targets (APK and bundle). - if (enable_64_bit_browser) { - libmonochrome_apk_or_bundle_tmpl("monochrome_64") { - is_bundle = false - } - libmonochrome_apk_or_bundle_tmpl("monochrome_64_base") { - is_bundle = true - } + libmonochrome_apk_or_bundle_tmpl("monochrome_64") { + is_bundle = false + } + libmonochrome_apk_or_bundle_tmpl("monochrome_64_base") { + is_bundle = true } # 32-bit browser library alias targets, pulled in by 64-bit WebView builds. @@ -2187,7 +2185,7 @@ } } -if (android_64bit_target_cpu && enable_64_bit_browser) { +if (android_64bit_target_cpu) { monochrome_public_bundle_tmpl("monochrome_64_public_bundle") { bundle_suffix = "64" is_64_bit_browser = true
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index f27be47a..a71fdbb 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -484,7 +484,6 @@ "javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcherTest.java", "javatests/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java", "javatests/src/org/chromium/chrome/browser/webapps/WebappActionsNotificationTest.java", - "javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTest.java", "javatests/src/org/chromium/chrome/browser/webapps/WebappAuthenticatorTest.java", "javatests/src/org/chromium/chrome/browser/webapps/WebappDeferredStartupTest.java", "javatests/src/org/chromium/chrome/browser/webapps/WebappDisplayModeTest.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 93f697b..5112350b 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
@@ -107,7 +107,7 @@ PostTask.postTask(UiThreadTaskTraits.USER_VISIBLE, () -> mFinalCallback.onResult(mMultiThumbnailBitmap)); } - }); + }, false); } else { drawBitmapOnCanvasWithFrame(null, i, mEmptyThumbnailPaint); if (mThumbnailsToFetch.decrementAndGet() == 0) { @@ -201,13 +201,14 @@ } @Override - public void getTabThumbnailWithCallback(Tab tab, Callback<Bitmap> finalCallback) { + public void getTabThumbnailWithCallback( + Tab tab, Callback<Bitmap> finalCallback, boolean forceUpdate) { if (mTabModelSelector.getTabModelFilterProvider() .getCurrentTabModelFilter() .getRelatedTabList(tab.getId()) .size() == 1) { - mTabContentManager.getTabThumbnailWithCallback(tab, finalCallback); + mTabContentManager.getTabThumbnailWithCallback(tab, finalCallback, forceUpdate); return; }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java index 0d4499a..96050bc 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java
@@ -83,6 +83,9 @@ } }; fetcher.fetch(callback); + } else if (TabProperties.IPH_PROVIDER == propertyKey) { + TabListMediator.IphProvider provider = item.get(TabProperties.IPH_PROVIDER); + if (provider != null) provider.showIPH(holder.thumbnail); } else if (TabProperties.TAB_ID == propertyKey) { holder.setTabId(item.get(TabProperties.TAB_ID)); } else if (TabProperties.CREATE_GROUP_LISTENER == propertyKey) {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java index 3e4c594..0ef0858f 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -7,9 +7,11 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.Drawable; +import android.os.Handler; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; +import android.view.View; import org.chromium.base.Callback; import org.chromium.base.metrics.RecordHistogram; @@ -25,6 +27,8 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelUtils; import org.chromium.chrome.browser.tabmodel.TabSelectionType; +import org.chromium.chrome.browser.tasks.tab_groups.TabGroupUtils; +import org.chromium.components.feature_engagement.FeatureConstants; import org.chromium.content_public.browser.NavigationHandle; import org.chromium.ui.modelutil.PropertyModel; @@ -38,11 +42,13 @@ * TODO(yusufo): Move some of the logic here to a parent component to make the above true. */ class TabListMediator { + private boolean mShownIPH; + /** * An interface to get the thumbnails to be shown inside the tab grid cards. */ public interface ThumbnailProvider { - void getTabThumbnailWithCallback(Tab tab, Callback<Bitmap> callback); + void getTabThumbnailWithCallback(Tab tab, Callback<Bitmap> callback, boolean forceUpdate); } /** @@ -57,18 +63,42 @@ static class ThumbnailFetcher { private ThumbnailProvider mThumbnailProvider; private Tab mTab; + private boolean mForceUpdate; - ThumbnailFetcher(ThumbnailProvider provider, Tab tab) { + ThumbnailFetcher(ThumbnailProvider provider, Tab tab, boolean forceUpdate) { mThumbnailProvider = provider; mTab = tab; + mForceUpdate = forceUpdate; } void fetch(Callback<Bitmap> callback) { - mThumbnailProvider.getTabThumbnailWithCallback(mTab, callback); + mThumbnailProvider.getTabThumbnailWithCallback(mTab, callback, mForceUpdate); } } /** + * An interface to show IPH for a tab. + */ + public interface IphProvider { void showIPH(View anchor); } + + private final IphProvider mIphProvider = new IphProvider() { + private static final int IPH_DELAY_MS = 1000; + + @Override + public void showIPH(View anchor) { + if (mShownIPH) return; + mShownIPH = true; + + new Handler().postDelayed( + () + -> TabGroupUtils.maybeShowIPH( + FeatureConstants.TAB_GROUPS_YOUR_TABS_ARE_TOGETHER_FEATURE, + anchor), + IPH_DELAY_MS); + } + }; + + /** * An interface to get the onClickListener for "Create group" button. */ public interface CreateGroupButtonProvider { @@ -353,6 +383,10 @@ createGroupButtonOnClickListener = mCreateGroupButtonProvider.getCreateGroupButtonOnClickListener(tab); } + boolean showIPH = false; + if (mCloseAllRelatedTabs && !mShownIPH) { + showIPH = getRelatedTabsForId(tab.getId()).size() > 1; + } PropertyModel tabInfo = new PropertyModel.Builder(TabProperties.ALL_KEYS_TAB_GRID) @@ -361,6 +395,7 @@ .with(TabProperties.FAVICON, mTabListFaviconProvider.getDefaultFaviconDrawable()) .with(TabProperties.IS_SELECTED, isSelected) + .with(TabProperties.IPH_PROVIDER, showIPH ? mIphProvider : null) .with(TabProperties.TAB_SELECTED_LISTENER, mTabSelectedListener) .with(TabProperties.TAB_CLOSED_LISTENER, mTabClosedListener) .with(TabProperties.CREATE_GROUP_LISTENER, createGroupButtonOnClickListener) @@ -383,7 +418,7 @@ tab.getUrl(), tab.isIncognito(), faviconCallback); if (mThumbnailProvider != null) { - ThumbnailFetcher callback = new ThumbnailFetcher(mThumbnailProvider, tab); + ThumbnailFetcher callback = new ThumbnailFetcher(mThumbnailProvider, tab, isSelected); tabInfo.set(TabProperties.THUMBNAIL_FETCHER, callback); } tab.addObserver(mTabObserver);
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java index 285f0f1..a6f68238 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabProperties.java
@@ -30,6 +30,9 @@ public static final WritableObjectPropertyKey<TabListMediator.ThumbnailFetcher> THUMBNAIL_FETCHER = new WritableObjectPropertyKey<>(); + public static final WritableObjectPropertyKey<TabListMediator.IphProvider> IPH_PROVIDER = + new WritableObjectPropertyKey<>(); + public static final WritableObjectPropertyKey<String> TITLE = new WritableObjectPropertyKey<>(); public static final WritableBooleanPropertyKey IS_SELECTED = new WritableBooleanPropertyKey(); @@ -40,9 +43,9 @@ public static final PropertyModel.WritableFloatPropertyKey ALPHA = new PropertyModel.WritableFloatPropertyKey(); - public static final PropertyKey[] ALL_KEYS_TAB_GRID = - new PropertyKey[] {TAB_ID, TAB_SELECTED_LISTENER, TAB_CLOSED_LISTENER, FAVICON, - THUMBNAIL_FETCHER, TITLE, IS_SELECTED, CREATE_GROUP_LISTENER, ALPHA}; + public static final PropertyKey[] ALL_KEYS_TAB_GRID = new PropertyKey[] {TAB_ID, + TAB_SELECTED_LISTENER, TAB_CLOSED_LISTENER, FAVICON, THUMBNAIL_FETCHER, IPH_PROVIDER, + TITLE, IS_SELECTED, CREATE_GROUP_LISTENER, ALPHA}; public static final PropertyKey[] ALL_KEYS_TAB_STRIP = new PropertyKey[] { TAB_ID, TAB_SELECTED_LISTENER, TAB_CLOSED_LISTENER, FAVICON, IS_SELECTED, TITLE};
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java index 30e8700..ad0092fe 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java
@@ -50,13 +50,14 @@ private TabListMediator.ThumbnailFetcher mMockThumbnailProvider = new TabListMediator.ThumbnailFetcher(new TabListMediator.ThumbnailProvider() { @Override - public void getTabThumbnailWithCallback(Tab tab, Callback<Bitmap> callback) { + public void getTabThumbnailWithCallback( + Tab tab, Callback<Bitmap> callback, boolean forceUpdate) { Bitmap bitmap = mShouldReturnBitmap ? Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) : null; callback.onResult(bitmap); } - }, null); + }, null, false); private TabListMediator.TabActionListener mMockCloseListener = new TabListMediator.TabActionListener() {
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherMediatorUnitTest.java index d24a540..248202a 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherMediatorUnitTest.java
@@ -8,6 +8,7 @@ import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; @@ -124,7 +125,9 @@ List<TabModel> tabModelList = new ArrayList<>(); tabModelList.add(mTabModel); - doNothing().when(mTabContentManager).getTabThumbnailWithCallback(any(), any()); + doNothing() + .when(mTabContentManager) + .getTabThumbnailWithCallback(any(), any(), anyBoolean()); doReturn(mResources).when(mContext).getResources(); doReturn(mTabModel).when(mTabModelSelector).getCurrentModel();
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java index 1cc94dc..b8e7fb1 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -108,7 +108,9 @@ List<TabModel> tabModelList = new ArrayList<>(); tabModelList.add(mTabModel); - doNothing().when(mTabContentManager).getTabThumbnailWithCallback(any(), any()); + doNothing() + .when(mTabContentManager) + .getTabThumbnailWithCallback(any(), any(), anyBoolean()); doReturn(mTabModel).when(mTabModelSelector).getCurrentModel(); doReturn(tabModelList).when(mTabModelSelector).getModels(); doReturn(mTabModelFilterProvider).when(mTabModelSelector).getTabModelFilterProvider();
diff --git a/chrome/android/java/res/drawable/logo_translate_round.xml b/chrome/android/java/res/drawable/logo_translate_round.xml index 438a031..dd6bf7c 100644 --- a/chrome/android/java/res/drawable/logo_translate_round.xml +++ b/chrome/android/java/res/drawable/logo_translate_round.xml
@@ -4,44 +4,28 @@ found in the LICENSE file. --> <vector - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:aapt="http://schemas.android.com/aapt" - xmlns:tools="http://schemas.android.com/tools" - android:height="24dp" android:viewportHeight="48" - android:viewportWidth="48" android:width="24dp" - tools:targetApi="21"> - - <path android:fillColor="#eee" android:pathData="M33.92,43.63C41.09,40.01 46,32.58 46,24c0,-12.15 -9.85,-22 -22,-22 -1.31,0 -2.59,0.12 -3.84,0.34l-0.9,1.6L32.27,43.1l1.65,0.53z"/> - <path android:fillColor="#607d8b" android:pathData="M24.71,19v-2h6.31v-2H33v2h6v2h-1.58c-0.57,2.33 -1.84,4.78 -3.46,6.64l4.89,4.85 -1.32,1.32 -4.85,-4.85 -4.85,4.85 -1.32,-1.32 4.89,-4.85c-1.16,-1.34 -2.17,-3.07 -2.85,-4.64h2.08c0.43,0.86 1.1,2.14 2.05,3.25 2.2,-2.57 2.81,-5.25 2.81,-5.25H24.71z"/> - <path android:fillAlpha=".2" android:fillColor="#fff" android:pathData="M24,2.23c12.11,0 21.94,9.79 22,21.89v-0.11c0,-12.15 -9.85,-22 -22,-22C11.85,2 2,11.85 2,24v0.11c0.06,-12.09 9.89,-21.88 22,-21.88z"/> - <path android:fillAlpha=".15" android:fillColor="#263238" android:pathData="M24,45.77c12.11,0 21.94,-9.79 22,-21.89v0.11c0,12.15 -9.85,22 -22,22C11.85,46 2,36.15 2,24v-0.11c0.06,12.09 9.89,21.88 22,21.88z"/> - <path android:fillAlpha=".1" android:pathData="M24,24m-22,0a22,22 0,1 1,44 0a22,22 0,1 1,-44 0"> - <aapt:attr name="android:fillColor"> - <gradient android:centerX="8.649595" - android:centerY="8.650356" - android:gradientRadius="43.711006" android:type="radial"> - <item android:color="#FFFFFFFF" android:offset="0"/> - <item android:color="#00FFFFFF" android:offset="1"/> - </gradient> - </aapt:attr> - </path> - <group> - <clip-path android:pathData="M24,24m-22,0a22,22 0,1 1,44 0a22,22 0,1 1,-44 0 M 0,0"/> - <path android:pathData="M20.03 2.25l32.38 32.38V56.9H22.05"> - <aapt:attr name="android:fillColor"> - <gradient android:endX="52.411" android:endY="29.579" - android:startX="20.03" android:startY="29.579" android:type="linear"> - <item android:color="#19212121" android:offset="0"/> - <item android:color="#05212121" android:offset="1"/> - </gradient> - </aapt:attr> - </path> - </group> - <group> - <clip-path android:pathData="M24,24m-22,0a22,22 0,1 1,44 0a22,22 0,1 1,-44 0 M 0,0"/> - <path android:fillColor="#4285f4" android:pathData="M2 24c0 12.15 9.85 22 22 22 3.57 0 6.94,-.85 9.93,-2.36L20.16 2.33C9.84 4.15 2 13.16 2 24z"/> - <path android:fillAlpha="0.1" android:fillColor="#fff" - android:pathData="M18.22,-2.68L35.2 48.24l.31.13L18.39,-2.96" android:strokeAlpha="0.1"/> - <path android:fillColor="#eee" android:pathData="M16.02 23v2h3.97c-.16 1.43,-1.2 3.42,-3.97 3.42,-2.39 0,-4.34,-1.98,-4.34,-4.42s1.95,-4.42 4.34,-4.42c1.36 0 2.27.58 2.79 1.08l1.9,-1.83c-1.22,-1.14,-2.8,-1.83,-4.69,-1.83,-3.87 0,-7 3.13,-7 7s3.13 7 7 7c4.04 0 6.72,-2.84 6.72,-6.84 0,-.46,-.05,-.81,-.11,-1.16h-6.61z"/> - </group> + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt" + xmlns:tools="http://schemas.android.com/tools" + android:width="36dp" + android:height="36dp" + android:viewportWidth="36.0" + android:viewportHeight="36.0" + tools:targetApi="21"> + <path + android:pathData="M18,0L18,0C27.94,-0 36,8.06 36,18L36,18C36,27.94 27.94,36 18,36L18,36C8.06,36 0,27.94 0,18L0,18C-0,8.06 8.06,0 18,0Z" + android:fillColor="@color/light_active_color" + /> + <path + android:pathData="M18.87,21.07L16.33,18.56L16.36,18.53C18.1,16.59 19.34,14.36 20.07,12L23,12L23,10L16,10L16,8L14,8L14,10L7,10L7,11.99L18.17,11.99C17.5,13.92 16.44,15.75 15,17.35C14.07,16.32 13.3,15.19 12.69,14L10.69,14C11.42,15.63 12.42,17.17 13.67,18.56L8.58,23.58L10,25L15,20L18.11,23.11L18.87,21.07Z" + android:fillColor="@color/default_icon_color_inverse" + /> + <path + android:pathData="M24.5,16l-2,0l-4.5,12l2,0l1.12,-3l4.75,0l1.13,3l2,0z" + android:fillColor="@color/default_icon_color_inverse" + /> + <path + android:pathData="M21.88,23l1.62,-4.33l1.62,4.33z" + android:fillColor="@color/light_active_color" + /> </vector>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabProvider.java index f555c64..e35c5266 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ActivityTabProvider.java
@@ -8,6 +8,7 @@ import org.chromium.base.ObserverList; import org.chromium.base.ObserverList.RewindableIterator; +import org.chromium.base.Supplier; import org.chromium.chrome.browser.compositor.layouts.Layout; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; import org.chromium.chrome.browser.compositor.layouts.SceneChangeObserver; @@ -23,7 +24,7 @@ /** * A class that provides the current {@link Tab} for various states of the browser's activity. */ -public class ActivityTabProvider { +public class ActivityTabProvider implements Supplier<Tab> { /** An interface to track the visible tab for the activity. */ public interface ActivityTabObserver { /** @@ -79,7 +80,7 @@ onObservingDifferentTab(tab); }; mTabProvider.addObserver(mActivityTabObserver); - updateObservedTab(mTabProvider.getActivityTab()); + updateObservedTab(mTabProvider.get()); } /** @@ -174,7 +175,8 @@ /** * @return The activity's current tab. */ - public Tab getActivityTab() { + @Override + public Tab get() { return mActivityTab; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingMediator.java index b2baace..7e03f03 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingMediator.java
@@ -430,7 +430,7 @@ * @return The currently visible {@link Tab}, if any. */ private @Nullable Tab getActiveBrowserTab() { - return mActivity.getActivityTabProvider().getActivityTab(); + return mActivity.getActivityTabProvider().get(); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityOpenTimeRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityOpenTimeRecorder.java index f582e66..6f1962d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityOpenTimeRecorder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityOpenTimeRecorder.java
@@ -71,7 +71,7 @@ mLastStateChangeTimestampMs = SystemClock.elapsedRealtime(); if (mInVerifiedOrigin && !mTwaOpenedRecorded) { - mRecorder.recordTwaOpened(mTabProvider.getActivityTab()); + mRecorder.recordTwaOpened(mTabProvider.get()); mTwaOpenedRecorded = true; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabPanel.java index 14dab02..58f83d4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabPanel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabPanel.java
@@ -213,7 +213,7 @@ closePanel(StateChangeReason.TAB_PROMOTION, false); mActivity.getCurrentTabCreator().createNewTab( new LoadUrlParams(mUrl, PageTransition.LINK), TabLaunchType.FROM_LINK, - mActivity.getActivityTabProvider().getActivityTab()); + mActivity.getActivityTabProvider().get()); } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java index 3d6b1c7..4ad1ccd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java
@@ -4,9 +4,13 @@ package org.chromium.chrome.browser.compositor.layouts.content; +import static java.lang.Math.min; + import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Matrix; +import android.support.annotation.Nullable; import android.view.View; import android.view.ViewGroup.MarginLayoutParams; @@ -242,10 +246,23 @@ * @param tab The tab to get the thumbnail for. * @param callback The callback to send the {@link Bitmap} with. */ - public void getTabThumbnailWithCallback(Tab tab, Callback<Bitmap> callback) { + public void getTabThumbnailWithCallback( + Tab tab, Callback<Bitmap> callback, boolean forceUpdate) { if (mNativeTabContentManager == 0 || !mSnapshotsEnabled) return; - nativeGetTabThumbnailWithCallback(mNativeTabContentManager, tab.getId(), callback); + if (forceUpdate) { + cacheTabThumbnail(tab, (bitmap) -> { + if (bitmap != null) { + callback.onResult(bitmap); + return; + } + // If invalidation is not needed, cacheTabThumbnail() might not do anything, so we + // need to fall back to reading from disk. + nativeGetTabThumbnailWithCallback(mNativeTabContentManager, tab.getId(), callback); + }); + } else { + nativeGetTabThumbnailWithCallback(mNativeTabContentManager, tab.getId(), callback); + } } /** @@ -253,16 +270,40 @@ * @param tab The tab whose content we will cache. */ public void cacheTabThumbnail(final Tab tab) { + cacheTabThumbnail(tab, null); + } + + /** + * Cache the content of a tab as a thumbnail. + * @param tab The tab whose content we will cache. + * @param callback The callback to send the {@link Bitmap} with. + */ + public void cacheTabThumbnail(final Tab tab, @Nullable Callback<Bitmap> callback) { if (mNativeTabContentManager != 0 && mSnapshotsEnabled) { if (tab.getNativePage() != null) { Bitmap nativePageBitmap = readbackNativePage(tab, mThumbnailScale); - if (nativePageBitmap == null) return; + if (nativePageBitmap == null) { + if (callback != null) callback.onResult(null); + return; + } nativeCacheTabWithBitmap(mNativeTabContentManager, tab, nativePageBitmap, mThumbnailScale); + if (callback != null) { + // In portrait mode, we want to show thumbnails in squares. + // Therefore, the thumbnail saved in portrait mode needs to be cropped to + // a square, or it would become too tall and break the layout. + Matrix matrix = new Matrix(); + matrix.setScale(0.5f, 0.5f); + Bitmap resized = + Bitmap.createBitmap(nativePageBitmap, 0, 0, nativePageBitmap.getWidth(), + min(nativePageBitmap.getWidth(), nativePageBitmap.getHeight()), + matrix, true); + callback.onResult(resized); + } nativePageBitmap.recycle(); } else { if (tab.getWebContents() == null) return; - nativeCacheTab(mNativeTabContentManager, tab, mThumbnailScale); + nativeCacheTab(mNativeTabContentManager, tab, mThumbnailScale, callback); } } } @@ -294,7 +335,7 @@ */ public void updateVisibleIds(List<Integer> priority, int primaryTabId) { if (mNativeTabContentManager != 0) { - int idsSize = Math.min(mFullResThumbnailsMaxSize, priority.size()); + int idsSize = min(mFullResThumbnailsMaxSize, priority.size()); if (idsSize != mPriorityTabIds.length) { mPriorityTabIds = new int[idsSize]; @@ -331,8 +372,8 @@ private native void nativeAttachTab(long nativeTabContentManager, Tab tab, int tabId); private native void nativeDetachTab(long nativeTabContentManager, Tab tab, int tabId); private native boolean nativeHasFullCachedThumbnail(long nativeTabContentManager, int tabId); - private native void nativeCacheTab( - long nativeTabContentManager, Object tab, float thumbnailScale); + private native void nativeCacheTab(long nativeTabContentManager, Object tab, + float thumbnailScale, Callback<Bitmap> callback); private native void nativeCacheTabWithBitmap(long nativeTabContentManager, Object tab, Object bitmap, float thumbnailScale); private native void nativeInvalidateIfChanged(long nativeTabContentManager, int tabId,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java index 18af8fb9..c34b3cb0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java
@@ -108,7 +108,7 @@ // This leaves the handling of the hooks to the responsibility of the activity tab. // Restoring them will be then done by the tab that was the activity tab when // the panel was shown. - Tab activityTab = mTab.getActivity().getActivityTabProvider().getActivityTab(); + Tab activityTab = mTab.getActivity().getActivityTabProvider().get(); if (activityTab != mTab) return; // Removes the hooks if the panel other than contextual search panel just got shown.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBrowserControlsVisibilityDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBrowserControlsVisibilityDelegate.java index 6ba6319d..9514770 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBrowserControlsVisibilityDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBrowserControlsVisibilityDelegate.java
@@ -72,7 +72,7 @@ } private void updateActiveTabFullscreenEnabledState() { - Tab activeTab = mTabProvider.getActivityTab(); + Tab activeTab = mTabProvider.get(); if (activeTab != null) { activeTab.updateFullscreenEnabledState(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java index 0c22e7b..79ffd006 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -121,7 +121,7 @@ /** * Indicates the source where the Custom Tab is launched. This is only used for * WebApp/WebAPK/TrustedWebActivity. The value is defined as - * {@link WebappActivity.ActivityType#WebappActivity}. + * {@link LaunchSourceType}. */ public static final String EXTRA_BROWSER_LAUNCH_SOURCE = "org.chromium.chrome.browser.customtabs.EXTRA_BROWSER_LAUNCH_SOURCE";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabProvider.java index fb5c627..76049ed8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabProvider.java
@@ -50,7 +50,7 @@ /** * Returns tab currently managed by the Custom Tab activity. * - * The difference from {@link ActivityTabProvider#getActivityTab()} is that we may have acquired + * The difference from {@link ActivityTabProvider#get()} is that we may have acquired * a hidden tab (see {@link CustomTabsConnection#takeHiddenTab}), which is not yet added to a * {@link TabModel}. In that case this method returns the hidden tab, and ActivityTabProvider * returns null.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModulePageLoadObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModulePageLoadObserver.java index b9b7abbc..b0b9cb73 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModulePageLoadObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModulePageLoadObserver.java
@@ -87,7 +87,7 @@ private void notifyOnPageMetricEvent(WebContents webContents, String metricName, long navigationStartTick, long offset, long navigationId) { - if (webContents != mActivityTabProvider.getActivityTab().getWebContents()) return; + if (webContents != mActivityTabProvider.get().getWebContents()) return; long navigationStartMs = (navigationStartTick - mNativeTickOffsetUs) / 1000; if (mActivityDelegate == null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java index f248d65c..3413832 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/HistoryNavigationLayout.java
@@ -69,7 +69,7 @@ mSideSlideLayout.setEnabled(false); mSideSlideLayout.setOnNavigationListener((isForward) -> { if (mTabProvider == null) return; - Tab tab = mTabProvider.getActivityTab(); + Tab tab = mTabProvider.get(); if (isForward) { tab.goForward(); } else { @@ -141,7 +141,7 @@ private boolean canNavigate(boolean forward) { if (mTabProvider == null) return false; - Tab tab = mTabProvider.getActivityTab(); + Tab tab = mTabProvider.get(); return forward ? tab.canGoForward() : tab.canGoBack(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java index 5ca8f18..4a14384 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java
@@ -10,7 +10,9 @@ import org.chromium.base.Callback; import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; -import org.chromium.base.task.AsyncTask; +import org.chromium.base.task.PostTask; +import org.chromium.base.task.TaskTraits; +import org.chromium.content_public.browser.UiThreadTaskTraits; import java.io.File; import java.io.FileInputStream; @@ -32,7 +34,7 @@ * * @param bridge Bridge used to interact with native. */ - protected CachedImageFetcher(ImageFetcherBridge bridge) { + CachedImageFetcher(ImageFetcherBridge bridge) { mImageFetcherBridge = bridge; } @@ -46,38 +48,70 @@ // Do nothing, this lives for the lifetime of the application. } + /** + * Tries to load the gif from disk, if not it falls back to the bridge. + */ @Override public void fetchGif(String url, String clientName, Callback<BaseGifImage> callback) { long startTimeMillis = System.currentTimeMillis(); - String filePath = mImageFetcherBridge.getFilePath(url); - // TODO(crbug.com/947176): Use the new PostTask api for deferred tasks. - new AsyncTask<BaseGifImage>() { - @Override - protected BaseGifImage doInBackground() { - return tryToLoadGifFromDisk(filePath); - } - - @Override - protected void onPostExecute(BaseGifImage gif) { - if (gif != null) { - callback.onResult(gif); - reportEvent(clientName, CachedImageFetcherEvent.JAVA_DISK_CACHE_HIT); - mImageFetcherBridge.reportCacheHitTime(clientName, startTimeMillis); - } else { - mImageFetcherBridge.fetchGif(url, clientName, (BaseGifImage gifFromNative) -> { - callback.onResult(gifFromNative); - mImageFetcherBridge.reportTotalFetchTimeFromNative( - clientName, startTimeMillis); - }); - } - } - }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + PostTask.postTask(TaskTraits.USER_VISIBLE, () -> { + // Try to read the gif from disk, then post back to the ui thread. + String filePath = mImageFetcherBridge.getFilePath(url); + BaseGifImage cachedGif = tryToLoadGifFromDisk(filePath); + PostTask.postTask(UiThreadTaskTraits.USER_VISIBLE, () -> { + continueFetchGifAfterDisk(url, clientName, callback, cachedGif, startTimeMillis); + }); + }); } + @VisibleForTesting + void continueFetchGifAfterDisk(String url, String clientName, Callback<BaseGifImage> callback, + BaseGifImage cachedGif, long startTimeMillis) { + if (cachedGif != null) { + callback.onResult(cachedGif); + reportEvent(clientName, CachedImageFetcherEvent.JAVA_DISK_CACHE_HIT); + mImageFetcherBridge.reportCacheHitTime(clientName, startTimeMillis); + } else { + mImageFetcherBridge.fetchGif(url, clientName, (BaseGifImage gifFromNative) -> { + callback.onResult(gifFromNative); + mImageFetcherBridge.reportTotalFetchTimeFromNative(clientName, startTimeMillis); + }); + } + } + + /** + * Tries to load the gif from disk, if not it falls back to the bridge. + */ @Override public void fetchImage( String url, String clientName, int width, int height, Callback<Bitmap> callback) { - fetchImageImpl(url, clientName, width, height, callback); + long startTimeMillis = System.currentTimeMillis(); + PostTask.postTask(TaskTraits.USER_VISIBLE, () -> { + // Try to read the bitmap from disk, then post back to the ui thread. + String filePath = mImageFetcherBridge.getFilePath(url); + Bitmap bitmap = tryToLoadImageFromDisk(filePath); + PostTask.postTask(UiThreadTaskTraits.USER_VISIBLE, () -> { + continueFetchImageAfterDisk( + url, clientName, width, height, callback, bitmap, startTimeMillis); + }); + }); + } + + @VisibleForTesting + void continueFetchImageAfterDisk(String url, String clientName, int width, int height, + Callback<Bitmap> callback, Bitmap cachedBitmap, long startTimeMillis) { + if (cachedBitmap != null) { + callback.onResult(cachedBitmap); + reportEvent(clientName, CachedImageFetcherEvent.JAVA_DISK_CACHE_HIT); + mImageFetcherBridge.reportCacheHitTime(clientName, startTimeMillis); + } else { + mImageFetcherBridge.fetchImage( + getConfig(), url, clientName, width, height, (Bitmap bitmapFromNative) -> { + callback.onResult(bitmapFromNative); + mImageFetcherBridge.reportTotalFetchTimeFromNative( + clientName, startTimeMillis); + }); + } } @Override @@ -85,45 +119,6 @@ return ImageFetcherConfig.DISK_CACHE_ONLY; } - /** - * Starts an AsyncTask to first check the disk for the desired image, then fetches from the - * network if it isn't found. - * - * @param url The url to fetch the image from. - * @param width The new bitmap's desired width (in pixels). - * @param height The new bitmap's desired height (in pixels). - * @param callback The function which will be called when the image is ready. - */ - @VisibleForTesting - void fetchImageImpl( - String url, String clientName, int width, int height, Callback<Bitmap> callback) { - long startTimeMillis = System.currentTimeMillis(); - String filePath = mImageFetcherBridge.getFilePath(url); - // TODO(crbug.com/947176): Use the new PostTask api for deferred tasks. - new AsyncTask<Bitmap>() { - @Override - protected Bitmap doInBackground() { - return tryToLoadImageFromDisk(filePath); - } - - @Override - protected void onPostExecute(Bitmap bitmap) { - if (bitmap != null) { - callback.onResult(bitmap); - reportEvent(clientName, CachedImageFetcherEvent.JAVA_DISK_CACHE_HIT); - mImageFetcherBridge.reportCacheHitTime(clientName, startTimeMillis); - } else { - mImageFetcherBridge.fetchImage(getConfig(), url, clientName, width, height, - (Bitmap bitmapFromNative) -> { - callback.onResult(bitmapFromNative); - mImageFetcherBridge.reportTotalFetchTimeFromNative( - clientName, startTimeMillis); - }); - } - } - }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } - /** Wrapper function to decode a file for disk, useful for testing. */ @VisibleForTesting Bitmap tryToLoadImageFromDisk(String filePath) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateInfoBarController.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateInfoBarController.java index 377cbdc..33a586ee 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateInfoBarController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateInfoBarController.java
@@ -73,7 +73,7 @@ private void showRestartInfobar() { if (mActivity == null) return; - Tab tab = mActivity.getActivityTabProvider().getActivityTab(); + Tab tab = mActivity.getActivityTabProvider().get(); if (tab == null) return; SimpleConfirmInfoBarBuilder.create(tab, @@ -103,7 +103,7 @@ private void showFailedInfobar() { if (mActivity == null) return; - Tab tab = mActivity.getActivityTabProvider().getActivityTab(); + Tab tab = mActivity.getActivityTabProvider().get(); if (tab == null) return; SimpleConfirmInfoBarBuilder.create(tab, @@ -138,4 +138,4 @@ Toast.LENGTH_LONG) .show(); } -} \ No newline at end of file +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java index 3f25431..e4c7571 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
@@ -148,7 +148,7 @@ @Override public boolean doesProcessSuggestion(OmniboxSuggestion suggestion) { - Tab activeTab = mTabProvider != null ? mTabProvider.getActivityTab() : null; + Tab activeTab = mTabProvider != null ? mTabProvider.get() : null; // The what-you-typed suggestion can potentially appear as the second suggestion in some // cases. If the first suggestion isn't the one we want, ignore all subsequent suggestions. @@ -208,7 +208,7 @@ } model.set(EditUrlSuggestionProperties.BUTTON_CLICK_LISTENER, this); - if (mOriginalTitle == null) mOriginalTitle = mTabProvider.getActivityTab().getTitle(); + if (mOriginalTitle == null) mOriginalTitle = mTabProvider.get().getTitle(); model.set(EditUrlSuggestionProperties.TITLE_TEXT, mOriginalTitle); model.set(EditUrlSuggestionProperties.URL_TEXT, mLastProcessedSuggestion.getUrl()); } @@ -256,7 +256,7 @@ @Override public void onClick(View view) { - Tab activityTab = mTabProvider.getActivityTab(); + Tab activityTab = mTabProvider.get(); assert activityTab != null : "A tab is required to make changes to the location bar."; if (R.id.url_copy_icon == view.getId()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java index 43879fa2..fcbd8d6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java
@@ -18,7 +18,7 @@ public class SendTabToSelfShareActivity extends ShareActivity { @Override protected void handleShareAction(ChromeActivity triggeringActivity) { - Tab tab = triggeringActivity.getActivityTabProvider().getActivityTab(); + Tab tab = triggeringActivity.getActivityTabProvider().get(); NavigationHistory history = tab.getWebContents().getNavigationController().getNavigationHistory();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java index 234eb4f..c3764512 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java
@@ -130,7 +130,7 @@ private boolean isActiveTabNTP() { if (mActivityTabProvider == null) return false; - final Tab tab = mActivityTabProvider.getActivityTab(); + final Tab tab = mActivityTabProvider.get(); if (tab == null) return false; return NewTabPage.isNTPUrl(tab.getUrl());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonInProductHelpController.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonInProductHelpController.java index a85e8929..3310a28 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonInProductHelpController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonInProductHelpController.java
@@ -69,7 +69,7 @@ @Override public void onPageLoadStarted(Tab tab, String url) { - if (tab != activity.getActivityTabProvider().getActivityTab()) return; + if (tab != activity.getActivityTabProvider().get()) return; mDataSavedOnStartPageLoad = DataReductionProxySettings.getInstance() .getContentLengthSavedInHistorySummary(); mPageLoadTab = tab; @@ -84,8 +84,7 @@ Tracker tracker = TrackerFactory.getTrackerForProfile(Profile.getLastUsedProfile()); if (dataSaved > 0L) tracker.notifyEvent(EventConstants.DATA_SAVED_ON_PAGE_LOAD); if (tab.isPreview()) tracker.notifyEvent(EventConstants.PREVIEWS_PAGE_LOADED); - if (tab == activity.getActivityTabProvider().getActivityTab() - && tab.isUserInteractable()) { + if (tab == activity.getActivityTabProvider().get() && tab.isUserInteractable()) { maybeShowDataSaverDetail(activity); maybeShowDataSaverMilestonePromo(activity); maybeShowPreviewVerboseStatus(activity); @@ -137,7 +136,7 @@ // Attempts to show an IPH text bubble for page in preview mode. private static void maybeShowPreviewVerboseStatus(ChromeActivity activity) { - if (!activity.getActivityTabProvider().getActivityTab().isPreview()) return; + if (!activity.getActivityTabProvider().get().isPreview()) return; final View anchorView = activity.getToolbarManager().getSecurityIconView(); if (anchorView == null) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index 647bdfc1..c6a7902 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -15,7 +15,6 @@ import android.os.Bundle; import android.os.StrictMode; import android.os.SystemClock; -import android.support.annotation.IntDef; import android.support.annotation.Nullable; import android.text.TextUtils; import android.view.View; @@ -64,8 +63,6 @@ import org.chromium.ui.base.PageTransition; import java.io.File; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; @@ -76,15 +73,6 @@ public class WebappActivity extends SingleTabActivity { public static final String WEBAPP_SCHEME = "webapp"; - // The activity type of WebappActivity. - @IntDef({ActivityType.WEBAPP, ActivityType.WEBAPK}) - @Retention(RetentionPolicy.SOURCE) - public @interface ActivityType { - int OTHER = -1; - int WEBAPP = 0; - int WEBAPK = 1; - } - private static final String TAG = "WebappActivity"; private static final String HISTOGRAM_NAVIGATION_STATUS = "Webapp.NavigationStatus"; private static final long MS_BEFORE_NAVIGATING_BACK_FROM_INTERSTITIAL = 1000;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetController.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetController.java index da49bfb..b150b27 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetController.java
@@ -242,7 +242,7 @@ * the browser (i.e. the tab switcher may be showing). */ private void unsuppressSheet() { - if (!mIsSuppressed || mTabProvider.getActivityTab() == null || !mWasShownForCurrentTab + if (!mIsSuppressed || mTabProvider.get() == null || !mWasShownForCurrentTab || isOtherUIObscuring() || VrModuleProvider.getDelegate().isInVr()) { return; } @@ -296,7 +296,7 @@ */ private boolean loadInternal(BottomSheetContent content) { if (content == mBottomSheet.getCurrentSheetContent()) return true; - if (mTabProvider.getActivityTab() == null) return false; + if (mTabProvider.get() == null) return false; BottomSheetContent shownContent = mBottomSheet.getCurrentSheetContent(); boolean shouldSuppressExistingContent = shownContent != null
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ActivityTabProviderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ActivityTabProviderTest.java index 6c17812..e01938a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ActivityTabProviderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ActivityTabProviderTest.java
@@ -51,7 +51,7 @@ public TestActivityTabTabObserver(ActivityTabProvider provider) { super(provider); mObserverMoveHelper = new CallbackHelper(); - mObservedTab = provider.getActivityTab(); + mObservedTab = provider.get(); } @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/OSKOverscrollTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/OSKOverscrollTest.java index 532bda6..f6e69080 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/OSKOverscrollTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/OSKOverscrollTest.java
@@ -151,7 +151,7 @@ int viewportHeightAfterCss = getViewportHeight(webContentsRef.get()); int keyboardHeight = mActivityTestRule.getActivity() .getActivityTabProvider() - .getActivityTab() + .get() .getWebContents() .getViewAndroidDelegate() .getSystemWindowInsetBottom();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/SubresourceFilterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/SubresourceFilterTest.java index 4c481e93..4ca609e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/SubresourceFilterTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/SubresourceFilterTest.java
@@ -16,6 +16,7 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisabledTest; import org.chromium.chrome.browser.infobar.AdsBlockedInfoBar; import org.chromium.chrome.browser.infobar.InfoBar; import org.chromium.chrome.browser.infobar.InfoBarContainer; @@ -90,6 +91,7 @@ @Test @MediumTest + @DisabledTest(message = "crbug.com/899903") public void resourceNotFiltered() throws Exception { String url = mTestServer.getURL(PAGE_WITH_JPG); mActivityTestRule.loadUrl(url); @@ -104,6 +106,7 @@ @Test @MediumTest + @DisabledTest(message = "crbug.com/899903") public void resourceFilteredClose() throws Exception { String url = mTestServer.getURL(PAGE_WITH_JPG); MockSafeBrowsingApiHandler.addMockResponse(url, METADATA_FOR_ENFORCEMENT); @@ -131,6 +134,7 @@ @Test @MediumTest + @DisabledTest(message = "crbug.com/899903") public void resourceFilteredClickLearnMore() throws Exception { String url = mTestServer.getURL(PAGE_WITH_JPG); MockSafeBrowsingApiHandler.addMockResponse(url, METADATA_FOR_ENFORCEMENT); @@ -172,6 +176,7 @@ @Test @MediumTest + @DisabledTest(message = "crbug.com/899903") public void resourceFilteredReload() throws Exception { String url = mTestServer.getURL(PAGE_WITH_JPG); MockSafeBrowsingApiHandler.addMockResponse(url, METADATA_FOR_ENFORCEMENT); @@ -203,6 +208,7 @@ } @Test + @DisabledTest(message = "crbug.com/899903") @MediumTest public void resourceNotFilteredWithWarning() throws Exception { String url = mTestServer.getURL(PAGE_WITH_JPG);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTest.java deleted file mode 100644 index aad59d6..0000000 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTest.java +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.webapps; - -import android.support.test.filters.SmallTest; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.LaunchSourceType; -import org.chromium.chrome.test.ChromeJUnit4ClassRunner; - -/** - * Tests for WebappActivity class. - */ -@RunWith(ChromeJUnit4ClassRunner.class) -public class WebappActivityTest { - @Test - @SmallTest - public void testActivityTypeMatchesLaunchSourceType() throws Exception { - Assert.assertEquals(LaunchSourceType.OTHER, WebappActivity.ActivityType.OTHER); - Assert.assertEquals(LaunchSourceType.WEBAPP, WebappActivity.ActivityType.WEBAPP); - Assert.assertEquals(LaunchSourceType.WEBAPK, WebappActivity.ActivityType.WEBAPK); - } -}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingControllerTest.java index 943d9985..cf5c11c 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingControllerTest.java
@@ -725,7 +725,7 @@ when(tab.getWebContents()).thenReturn(mLastMockWebContents); mCache.getStateFor(tab).getWebContentsObserverForTesting().wasShown(); when(tab.getContentView()).thenReturn(mMockContentView); - when(mMockActivity.getActivityTabProvider().getActivityTab()).thenReturn(tab); + when(mMockActivity.getActivityTabProvider().get()).thenReturn(tab); when(mMockTabModelSelector.getCurrentTab()).thenReturn(tab); mediator.getTabModelObserverForTesting().didAddTab(tab, FROM_BROWSER_ACTIONS); mediator.getTabObserverForTesting().onShown(tab, FROM_NEW);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java index 823e5225..5c13b0a 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
@@ -162,7 +162,7 @@ } public void changeTab(Tab newTab) { - when(activityTabProvider.getActivityTab()).thenReturn(newTab); + when(activityTabProvider.get()).thenReturn(newTab); for (ActivityTabObserver observer : activityTabObserverCaptor.getAllValues()) { observer.onActivityTabChanged(newTab, false); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcherTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcherTest.java index 35c3a3b..95a3b32 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcherTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcherTest.java
@@ -15,7 +15,6 @@ import static org.mockito.Mockito.verify; import android.graphics.Bitmap; -import android.support.test.filters.SmallTest; import org.junit.Before; import org.junit.Test; @@ -27,12 +26,9 @@ import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.robolectric.annotation.Config; -import org.robolectric.shadows.ShadowLooper; import org.chromium.base.Callback; -import org.chromium.base.task.test.BackgroundShadowAsyncTask; import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulatorTest.ShadowUrlUtilities; import jp.tomorrowkey.android.gifplayer.BaseGifImage; @@ -40,13 +36,13 @@ * Unit tests for CachedImageFetcher. */ @RunWith(BaseRobolectricTestRunner.class) -@Config(manifest = Config.NONE, - shadows = {ShadowUrlUtilities.class, BackgroundShadowAsyncTask.class}) +@Config(manifest = Config.NONE) public class CachedImageFetcherTest { private static final String UMA_CLIENT_NAME = "TestUmaClient"; private static final String URL = "http://foo.bar"; private static final int WIDTH_PX = 100; private static final int HEIGHT_PX = 200; + private static final long START_TIME = 274127; CachedImageFetcher mCachedImageFetcher; @@ -75,85 +71,36 @@ } @Test - @SmallTest public void testFetchImageWithDimensionsFoundOnDisk() throws Exception { - Mockito.doReturn(mBitmap).when(mCachedImageFetcher).tryToLoadImageFromDisk(anyObject()); - mCachedImageFetcher.fetchImage(URL, UMA_CLIENT_NAME, WIDTH_PX, HEIGHT_PX, - (Bitmap bitmap) -> { assertEquals(bitmap, mBitmap); }); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + mCachedImageFetcher.continueFetchImageAfterDisk(URL, UMA_CLIENT_NAME, WIDTH_PX, HEIGHT_PX, + (Bitmap bitmap) -> { assertEquals(bitmap, mBitmap); }, mBitmap, START_TIME); - verify(mCachedImageFetcher) - .fetchImageImpl(eq(URL), eq(UMA_CLIENT_NAME), eq(WIDTH_PX), eq(HEIGHT_PX), any()); verify(mImageFetcherBridge, never()) // Should never make it to native. .fetchImage(anyInt(), eq(URL), eq(UMA_CLIENT_NAME), anyInt(), anyInt(), any()); // Verify metrics have been reported. verify(mImageFetcherBridge) .reportEvent(eq(UMA_CLIENT_NAME), eq(CachedImageFetcherEvent.JAVA_DISK_CACHE_HIT)); - verify(mImageFetcherBridge).reportCacheHitTime(eq(UMA_CLIENT_NAME), anyLong()); + verify(mImageFetcherBridge).reportCacheHitTime(eq(UMA_CLIENT_NAME), eq(START_TIME)); } @Test - @SmallTest public void testFetchImageWithDimensionsCallToNative() throws Exception { - Mockito.doReturn(null).when(mCachedImageFetcher).tryToLoadImageFromDisk(anyObject()); - mCachedImageFetcher.fetchImage(URL, UMA_CLIENT_NAME, WIDTH_PX, HEIGHT_PX, - (Bitmap bitmap) -> { assertEquals(bitmap, mBitmap); }); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + mCachedImageFetcher.continueFetchImageAfterDisk(URL, UMA_CLIENT_NAME, WIDTH_PX, HEIGHT_PX, + (Bitmap bitmap) -> { assertEquals(bitmap, mBitmap); }, null, START_TIME); - verify(mCachedImageFetcher) - .fetchImageImpl(eq(URL), eq(UMA_CLIENT_NAME), eq(WIDTH_PX), eq(HEIGHT_PX), any()); verify(mImageFetcherBridge) .fetchImage(anyInt(), eq(URL), eq(UMA_CLIENT_NAME), anyInt(), anyInt(), any()); } @Test - @SmallTest - public void testFetchImageWithNoDimensionsFoundOnDisk() throws Exception { - Mockito.doReturn(mBitmap).when(mCachedImageFetcher).tryToLoadImageFromDisk(anyObject()); - mCachedImageFetcher.fetchImage( - URL, UMA_CLIENT_NAME, (Bitmap bitmap) -> { assertEquals(bitmap, mBitmap); }); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - verify(mCachedImageFetcher) - .fetchImageImpl(eq(URL), eq(UMA_CLIENT_NAME), eq(0), eq(0), any()); - verify(mImageFetcherBridge, never()) - .fetchImage(anyInt(), eq(URL), eq(UMA_CLIENT_NAME), anyInt(), anyInt(), any()); - } - - @Test - @SmallTest - public void testFetchImageWithNoDimensionsCallToNative() throws Exception { - Mockito.doReturn(null).when(mCachedImageFetcher).tryToLoadImageFromDisk(anyObject()); - mCachedImageFetcher.fetchImage( - URL, UMA_CLIENT_NAME, (Bitmap bitmap) -> { assertEquals(bitmap, mBitmap); }); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); - - verify(mCachedImageFetcher) - .fetchImageImpl(eq(URL), eq(UMA_CLIENT_NAME), eq(0), eq(0), any()); - verify(mImageFetcherBridge) - .fetchImage(anyInt(), eq(URL), eq(UMA_CLIENT_NAME), anyInt(), anyInt(), any()); - } - - @Test - @SmallTest public void testFetchTwoClients() throws Exception { Mockito.doReturn(null).when(mCachedImageFetcher).tryToLoadImageFromDisk(anyObject()); - mCachedImageFetcher.fetchImage( - URL, UMA_CLIENT_NAME, (Bitmap bitmap) -> { assertEquals(bitmap, mBitmap); }); - mCachedImageFetcher.fetchImage( - URL, UMA_CLIENT_NAME + "2", (Bitmap bitmap) -> { assertEquals(bitmap, mBitmap); }); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + mCachedImageFetcher.continueFetchImageAfterDisk(URL, UMA_CLIENT_NAME, WIDTH_PX, HEIGHT_PX, + (Bitmap bitmap) -> { assertEquals(bitmap, mBitmap); }, null, START_TIME); + mCachedImageFetcher.continueFetchImageAfterDisk(URL, UMA_CLIENT_NAME + "2", WIDTH_PX, + HEIGHT_PX, (Bitmap bitmap) -> { assertEquals(bitmap, mBitmap); }, null, START_TIME); - verify(mCachedImageFetcher) - .fetchImageImpl(eq(URL), eq(UMA_CLIENT_NAME), eq(0), eq(0), any()); - verify(mCachedImageFetcher) - .fetchImageImpl(eq(URL), eq(UMA_CLIENT_NAME + "2"), eq(0), eq(0), any()); verify(mImageFetcherBridge) .fetchImage(anyInt(), eq(URL), eq(UMA_CLIENT_NAME), anyInt(), anyInt(), any()); verify(mImageFetcherBridge) @@ -162,13 +109,9 @@ } @Test - @SmallTest public void testFetchGifFoundOnDisk() throws Exception { - Mockito.doReturn(mGif).when(mCachedImageFetcher).tryToLoadGifFromDisk(anyObject()); - mCachedImageFetcher.fetchGif( - URL, UMA_CLIENT_NAME, (BaseGifImage gif) -> { assertEquals(gif, mGif); }); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + mCachedImageFetcher.continueFetchGifAfterDisk(URL, UMA_CLIENT_NAME, + (BaseGifImage gif) -> { assertEquals(gif, mGif); }, mGif, START_TIME); verify(mImageFetcherBridge, never()) // Should never make it to native. .fetchGif(eq(URL), eq(UMA_CLIENT_NAME), any()); @@ -180,12 +123,9 @@ } @Test - @SmallTest public void testFetchGifCallToNative() throws Exception { - Mockito.doReturn(null).when(mCachedImageFetcher).tryToLoadGifFromDisk(anyObject()); - mCachedImageFetcher.fetchGif(URL, UMA_CLIENT_NAME, (BaseGifImage gif) -> {}); - BackgroundShadowAsyncTask.runBackgroundTasks(); - ShadowLooper.runUiThreadTasks(); + mCachedImageFetcher.continueFetchGifAfterDisk(URL, UMA_CLIENT_NAME, + (BaseGifImage gif) -> { assertEquals(gif, mGif); }, null, START_TIME); verify(mImageFetcherBridge).fetchGif(eq(URL), eq(UMA_CLIENT_NAME), any()); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivityTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivityTest.java index b6d7611..3a0472a3 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivityTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivityTest.java
@@ -89,7 +89,7 @@ public void testHandleShareAction() { // Setup the mocked object chain to get to the profile. when(mChromeActivity.getActivityTabProvider()).thenReturn(mActivityTabProvider); - when(mActivityTabProvider.getActivityTab()).thenReturn(mTab); + when(mActivityTabProvider.get()).thenReturn(mTab); when(mTab.getProfile()).thenReturn(mProfile); // Setup the mocked object chain to get to the url, title and timestamp.
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index cd69176..c1c24986 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -4972,6 +4972,9 @@ <message name="IDS_NTP_CUSTOM_BG_BACK_LABEL" desc="Accessibility label for the back arrow on the background picker dialog. (On the New Tab Page)"> Back </message> + <message name="IDS_NTP_CUSTOM_BG_IMAGE_SELECTED" desc="Label to indicate that an image has been selected in the background picker dialog. (On the New Tab Page)"> + selected + </message> <message name="IDS_NTP_CUSTOM_BG_CUSTOMIZE_NTP_LABEL" desc="Accessibility label for the gear icon. (On the New Tab Page)"> Customize this page </message>
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_CUSTOM_BG_IMAGE_SELECTED.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_CUSTOM_BG_IMAGE_SELECTED.png.sha1 new file mode 100644 index 0000000..615793f --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_NTP_CUSTOM_BG_IMAGE_SELECTED.png.sha1
@@ -0,0 +1 @@ +96471032cdaa48350474e0e527b5aa23e191d898
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index ff8d90b..9719d50 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -2559,11 +2559,11 @@ <message name="IDS_SETTINGS_SAFEBROWSING_ENABLE_REPORTING_DESC" desc="Description for extended safe browsing"> Sends some system information and page content to Google </message> - <message name="IDS_SETTINGS_SPELLING_PREF" desc="The documentation string of the 'Use Spelling' preference"> - Use a web service to help resolve spelling errors + <message name="IDS_SETTINGS_SPELLING_PREF" desc="Label for a setting that enhances spell check by sending the text that users type to Google for spelling suggestions."> + Use enhanced spell check </message> <message name="IDS_SETTINGS_SPELLING_DESCRIPTION" desc="Description of using a web serviced to help resolve spelling errors. It is important to convey that what the user types will be sent to Google."> - Smarter spell-checking by sending what you type in the browser to Google + Chrome sends the text you type in the browser to Google </message> <message name="IDS_SETTINGS_SPELLING_PREF_UNIFIED_CONSENT" desc="The documentation string of the 'Use Spelling' preference"> Enhanced spell check
diff --git a/chrome/browser/android/compositor/tab_content_manager.cc b/chrome/browser/android/compositor/tab_content_manager.cc index c2a97c27..c5d515f1 100644 --- a/chrome/browser/android/compositor/tab_content_manager.cc +++ b/chrome/browser/android/compositor/tab_content_manager.cc
@@ -42,7 +42,7 @@ namespace { const size_t kMaxReadbacks = 1; -typedef base::Callback<void(float, const SkBitmap&)> TabReadbackCallback; +using TabReadbackCallback = base::OnceCallback<void(float, const SkBitmap&)>; } // namespace @@ -52,9 +52,9 @@ public: TabReadbackRequest(content::RenderWidgetHostView* rwhv, float thumbnail_scale, - const TabReadbackCallback& end_callback) + TabReadbackCallback end_callback) : thumbnail_scale_(thumbnail_scale), - end_callback_(end_callback), + end_callback_(std::move(end_callback)), drop_after_readback_(false), weak_factory_(this) { DCHECK(rwhv); @@ -78,13 +78,13 @@ void OnFinishGetTabThumbnailBitmap(const SkBitmap& bitmap) { if (bitmap.drawsNothing() || drop_after_readback_) { - end_callback_.Run(0.f, SkBitmap()); + std::move(end_callback_).Run(0.f, SkBitmap()); return; } SkBitmap result_bitmap = bitmap; result_bitmap.setImmutable(); - end_callback_.Run(thumbnail_scale_, bitmap); + std::move(end_callback_).Run(thumbnail_scale_, bitmap); } void SetToDropAfterReadback() { drop_after_readback_ = true; } @@ -211,16 +211,16 @@ return thumbnail_cache_->Get(tab_id, false, false) != nullptr; } -void TabContentManager::CacheTab(JNIEnv* env, - const JavaParamRef<jobject>& obj, - const JavaParamRef<jobject>& tab, - jfloat thumbnail_scale) { +content::RenderWidgetHostView* TabContentManager::GetRwhvForTab( + JNIEnv* env, + const JavaParamRef<jobject>& obj, + const JavaParamRef<jobject>& tab) { TabAndroid* tab_android = TabAndroid::GetNativeTab(env, tab); DCHECK(tab_android); const int tab_id = tab_android->GetAndroidId(); if (pending_tab_readbacks_.find(tab_id) != pending_tab_readbacks_.end() || pending_tab_readbacks_.size() >= kMaxReadbacks) { - return; + return nullptr; } content::WebContents* web_contents = tab_android->web_contents(); @@ -229,27 +229,49 @@ content::RenderViewHost* rvh = web_contents->GetRenderViewHost(); if (web_contents->ShowingInterstitialPage()) { if (!web_contents->GetInterstitialPage()->GetMainFrame()) - return; + return nullptr; - rvh = web_contents->GetInterstitialPage()->GetMainFrame()-> - GetRenderViewHost(); + rvh = web_contents->GetInterstitialPage() + ->GetMainFrame() + ->GetRenderViewHost(); } if (!rvh) - return; + return nullptr; content::RenderWidgetHost* rwh = rvh->GetWidget(); content::RenderWidgetHostView* rwhv = rwh ? rwh->GetView() : nullptr; if (!rwhv || !rwhv->IsSurfaceAvailableForCopy()) - return; + return nullptr; - if (thumbnail_cache_->CheckAndUpdateThumbnailMetaData( - tab_id, tab_android->GetURL())) { - TabReadbackCallback readback_done_callback = - base::Bind(&TabContentManager::PutThumbnailIntoCache, - weak_factory_.GetWeakPtr(), tab_id); - pending_tab_readbacks_[tab_id] = std::make_unique<TabReadbackRequest>( - rwhv, thumbnail_scale, readback_done_callback); + if (!thumbnail_cache_->CheckAndUpdateThumbnailMetaData(tab_id, + tab_android->GetURL())) + return nullptr; + + return rwhv; +} + +void TabContentManager::CacheTab( + JNIEnv* env, + const JavaParamRef<jobject>& obj, + const JavaParamRef<jobject>& tab, + jfloat thumbnail_scale, + const base::android::JavaParamRef<jobject>& j_callback) { + content::RenderWidgetHostView* rwhv = GetRwhvForTab(env, obj, tab); + if (!rwhv) { + if (j_callback) + RunObjectCallbackAndroid(j_callback, nullptr); + return; } + + TabAndroid* tab_android = TabAndroid::GetNativeTab(env, tab); + DCHECK(tab_android); + const int tab_id = tab_android->GetAndroidId(); + + TabReadbackCallback readback_done_callback = base::BindOnce( + &TabContentManager::PutThumbnailIntoCache, weak_factory_.GetWeakPtr(), + tab_id, base::android::ScopedJavaGlobalRef<jobject>(j_callback)); + pending_tab_readbacks_[tab_id] = std::make_unique<TabReadbackRequest>( + rwhv, thumbnail_scale, std::move(readback_done_callback)); } void TabContentManager::CacheTabWithBitmap(JNIEnv* env, @@ -267,7 +289,7 @@ skbitmap.setImmutable(); if (thumbnail_cache_->CheckAndUpdateThumbnailMetaData(tab_id, url)) - PutThumbnailIntoCache(tab_id, thumbnail_scale, skbitmap); + PutThumbnailIntoCache(tab_id, nullptr, thumbnail_scale, skbitmap); } void TabContentManager::InvalidateIfChanged(JNIEnv* env, @@ -313,10 +335,10 @@ jint tab_id, const base::android::JavaParamRef<jobject>& j_callback) { thumbnail_cache_->DecompressThumbnailFromFile( - tab_id, base::BindRepeating( - &TabContentManager::TabThumbnailAvailableFromDisk, - weak_factory_.GetWeakPtr(), - base::android::ScopedJavaGlobalRef<jobject>(j_callback))); + tab_id, + base::BindRepeating( + &TabContentManager::TabThumbnailAvailable, weak_factory_.GetWeakPtr(), + base::android::ScopedJavaGlobalRef<jobject>(j_callback))); } void TabContentManager::OnUIResourcesWereEvicted() { @@ -329,20 +351,26 @@ env, weak_java_tab_content_manager_.get(env), tab_id); } -void TabContentManager::PutThumbnailIntoCache(int tab_id, - float thumbnail_scale, - const SkBitmap& bitmap) { +void TabContentManager::PutThumbnailIntoCache( + int tab_id, + base::android::ScopedJavaGlobalRef<jobject> j_callback, + float thumbnail_scale, + const SkBitmap& bitmap) { TabReadbackRequestMap::iterator readback_iter = pending_tab_readbacks_.find(tab_id); if (readback_iter != pending_tab_readbacks_.end()) pending_tab_readbacks_.erase(tab_id); + if (j_callback) { + TabThumbnailAvailable(j_callback, true, bitmap); + } + if (thumbnail_scale > 0 && !bitmap.empty()) thumbnail_cache_->Put(tab_id, bitmap, thumbnail_scale); } -void TabContentManager::TabThumbnailAvailableFromDisk( +void TabContentManager::TabThumbnailAvailable( base::android::ScopedJavaGlobalRef<jobject> j_callback, bool result, SkBitmap bitmap) {
diff --git a/chrome/browser/android/compositor/tab_content_manager.h b/chrome/browser/android/compositor/tab_content_manager.h index f2154891..abe38a2 100644 --- a/chrome/browser/android/compositor/tab_content_manager.h +++ b/chrome/browser/android/compositor/tab_content_manager.h
@@ -17,6 +17,7 @@ #include "base/memory/weak_ptr.h" #include "cc/layers/ui_resource_layer.h" #include "chrome/browser/android/thumbnail/thumbnail_cache.h" +#include "content/public/browser/render_widget_host_view.h" using base::android::ScopedJavaLocalRef; @@ -83,7 +84,8 @@ void CacheTab(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jobject>& tab, - jfloat thumbnail_scale); + jfloat thumbnail_scale, + const base::android::JavaParamRef<jobject>& j_callback); void CacheTabWithBitmap(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jobject>& tab, @@ -120,11 +122,17 @@ using TabReadbackRequestMap = base::flat_map<int, std::unique_ptr<TabReadbackRequest>>; - void PutThumbnailIntoCache(int tab_id, - float thumbnail_scale, - const SkBitmap& bitmap); + content::RenderWidgetHostView* GetRwhvForTab( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj, + const base::android::JavaParamRef<jobject>& tab); + void PutThumbnailIntoCache( + int tab_id, + base::android::ScopedJavaGlobalRef<jobject> j_callback, + float thumbnail_scale, + const SkBitmap& bitmap); - void TabThumbnailAvailableFromDisk( + void TabThumbnailAvailable( base::android::ScopedJavaGlobalRef<jobject> j_callback, bool result, SkBitmap bitmap);
diff --git a/chrome/browser/android/subresource_filter/test_subresource_filter_publisher.cc b/chrome/browser/android/subresource_filter/test_subresource_filter_publisher.cc index 3031275..35f346e2b 100644 --- a/chrome/browser/android/subresource_filter/test_subresource_filter_publisher.cc +++ b/chrome/browser/android/subresource_filter/test_subresource_filter_publisher.cc
@@ -19,7 +19,6 @@ #include "base/files/scoped_temp_dir.h" #include "base/numerics/safe_conversions.h" #include "base/threading/thread_restrictions.h" -#include "chrome/browser/after_startup_task_utils.h" #include "chrome/browser/browser_process.h" #include "components/subresource_filter/content/browser/ruleset_service.h" #include "components/subresource_filter/core/common/unindexed_ruleset.h" @@ -72,9 +71,6 @@ base::android::ScopedJavaGlobalRef<jobject> publisher; publisher.Reset(env, publisher_param); - // Set the startup as complete, so tasks execute immediately. - AfterStartupTaskUtils::SetBrowserStartupIsCompleteForTesting(); - // Create the ruleset contents. std::string ruleset_contents_str; google::protobuf::io::StringOutputStream output(&ruleset_contents_str);
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 6cfb8bc..87b10e7 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -650,6 +650,9 @@ <include name="IDR_DEVICE_EMULATOR_PAGES_HTML" file="resources\chromeos\emulator\device_emulator_pages.html" type="BINDATA" /> <include name="IDR_DEVICE_EMULATOR_PAGES_JS" file="resources\chromeos\emulator\device_emulator_pages.js" type="BINDATA" /> <include name="IDR_DEVICE_EMULATOR_SHARED_STYLES_HTML" file="resources\chromeos\emulator\shared_styles.html" type="BINDATA" /> + <!-- TODO(jamescook): Create separate files os_settings.grd and + os_settings_vulcanized.grd and move this placeholder. --> + <include name="IDR_OS_SETTINGS_HTML" file="resources\chromeos\os_settings.html" type="BINDATA" compress="gzip" /> </if> <if expr="chromeos"> <include name="IDR_SET_TIME_HTML" file="resources\chromeos\md_set_time\set_time.html" type="BINDATA" compress="gzip" />
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 6e2c0a3..bd231c5 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -83,6 +83,7 @@ "//chromeos/components/drivefs/mojom", "//chromeos/components/multidevice", "//chromeos/components/multidevice/logging", + "//chromeos/components/power", "//chromeos/components/proximity_auth", "//chromeos/components/tether", "//chromeos/cryptohome",
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 62358d8..4acfefe 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -126,6 +126,7 @@ #include "chromeos/audio/audio_devices_pref_handler_impl.h" #include "chromeos/audio/cras_audio_handler.h" #include "chromeos/components/drivefs/fake_drivefs_launcher_client.h" +#include "chromeos/components/power/dark_resume_controller.h" #include "chromeos/constants/chromeos_features.h" #include "chromeos/constants/chromeos_switches.h" #include "chromeos/cryptohome/async_method_caller.h" @@ -145,7 +146,6 @@ #include "chromeos/network/network_cert_loader.h" #include "chromeos/network/network_handler.h" #include "chromeos/network/portal_detector/network_portal_detector_stub.h" -#include "chromeos/system/dark_resume_controller.h" #include "chromeos/system/statistics_provider.h" #include "chromeos/tpm/install_attributes.h" #include "chromeos/tpm/tpm_token_loader.h"
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc index 2d3e3b8..b981be25 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager.cc +++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -1837,11 +1837,9 @@ weak_ptr_factory_.GetWeakPtr(), vm_name, std::move(callback), CrostiniResult::SUCCESS)); - // Share folders from Downloads, etc with default VM. - if (vm_name == kCrostiniDefaultVmName) { - CrostiniSharePath::GetForProfile(profile_)->SharePersistedPaths( - base::DoNothing()); - } + // Share folders from Downloads, etc with VM. + CrostiniSharePath::GetForProfile(profile_)->SharePersistedPaths( + vm_name, base::DoNothing()); } void CrostiniManager::OnStartTremplin(std::string vm_name,
diff --git a/chrome/browser/chromeos/crostini/crostini_pref_names.cc b/chrome/browser/chromeos/crostini/crostini_pref_names.cc index c12dc2b7c..950bca1 100644 --- a/chrome/browser/chromeos/crostini/crostini_pref_names.cc +++ b/chrome/browser/chromeos/crostini/crostini_pref_names.cc
@@ -20,6 +20,8 @@ const char kCrostiniMimeTypes[] = "crostini.mime_types"; const char kCrostiniRegistry[] = "crostini.registry"; // List of filesystem paths that are shared with the crostini container. +// TODO(crbug.com/946273): Remove crostini.shared_paths and migration code after +// M77. const char kCrostiniSharedPaths[] = "crostini.shared_paths"; // List of USB devices with their system guid, a name/description and their // enabled state for use with Crostini. @@ -47,12 +49,17 @@ // The value of the last sample of the disk space used by Crostini. const char kCrostiniLastDiskSize[] = "crostini.last_disk_size"; +// Dictionary of filesystem paths mapped to the list of VMs that the paths are +// shared with. +const char kGuestOSPathsSharedToVms[] = "guest_os.paths_shared_to_vms"; + void RegisterProfilePrefs(PrefRegistrySimple* registry) { registry->RegisterBooleanPref(kCrostiniEnabled, false); registry->RegisterDictionaryPref(kCrostiniMimeTypes); registry->RegisterDictionaryPref(kCrostiniRegistry); registry->RegisterListPref(kCrostiniSharedPaths); registry->RegisterListPref(kCrostiniSharedUsbDevices); + registry->RegisterDictionaryPref(kGuestOSPathsSharedToVms); // Set a default value for crostini.containers to ensure that we track the // default container even if its creation predates this preference. This
diff --git a/chrome/browser/chromeos/crostini/crostini_pref_names.h b/chrome/browser/chromeos/crostini/crostini_pref_names.h index 556e57b..ae2a24d 100644 --- a/chrome/browser/chromeos/crostini/crostini_pref_names.h +++ b/chrome/browser/chromeos/crostini/crostini_pref_names.h
@@ -27,6 +27,8 @@ extern const char kCrostiniLastLaunchTimeWindowStart[]; extern const char kCrostiniLastDiskSize[]; +extern const char kGuestOSPathsSharedToVms[]; + void RegisterProfilePrefs(PrefRegistrySimple* registry); } // namespace prefs
diff --git a/chrome/browser/chromeos/crostini/crostini_share_path.cc b/chrome/browser/chromeos/crostini/crostini_share_path.cc index 32af7e1b..e0000b8 100644 --- a/chrome/browser/chromeos/crostini/crostini_share_path.cc +++ b/chrome/browser/chromeos/crostini/crostini_share_path.cc
@@ -122,6 +122,31 @@ std::string first_failure_reason_; }; // class +void RemovePersistedPathFromPrefs(base::DictionaryValue* shared_paths, + const std::string& vm_name, + const base::FilePath& path) { + // |shared_paths| format is {'path': ['vm1', vm2']}. + // If |path| exists, remove |vm_name| from list of VMs. + base::Value* found = shared_paths->FindKey(path.value()); + if (!found) { + LOG(WARNING) << "Path not in prefs to ushare path " << path.value() + << " for VM " << vm_name; + return; + } + auto& vms = found->GetList(); + auto it = std::find(vms.begin(), vms.end(), base::Value(vm_name)); + if (it == vms.end()) { + LOG(WARNING) << "VM not in prefs to ushare path " << path.value() + << " for VM " << vm_name; + return; + } + vms.erase(it); + // If VM list is now empty, remove |path| from |shared_paths|. + if (vms.size() == 0) { + shared_paths->RemoveKey(path.value()); + } +} + } // namespace namespace crostini { @@ -205,7 +230,7 @@ request.set_storage_location( vm_tools::seneschal::SharePathRequest::DOWNLOADS); } - request.set_owner_id(crostini::CryptohomeIdForProfile(profile_)); + request.set_owner_id(CryptohomeIdForProfile(profile_)); } else if (base::FeatureList::IsEnabled(chromeos::features::kDriveFs) && integration_service && (drivefs_mount_point_path = @@ -275,7 +300,7 @@ // Even if VM is not running, save to prefs now. if (persist) { - RegisterPersistedPath(path); + RegisterPersistedPath(vm_name, path); } RegisterSharedPath(vm_name, path); @@ -383,11 +408,10 @@ if (unpersist) { PrefService* pref_service = profile_->GetPrefs(); - ListPrefUpdate update(pref_service, crostini::prefs::kCrostiniSharedPaths); - base::ListValue* shared_paths = update.Get(); - if (!shared_paths->Remove(base::Value(path.value()), nullptr)) { - LOG(WARNING) << "Unshared path not in prefs: " << path.value(); - } + DictionaryPrefUpdate update(pref_service, + crostini::prefs::kGuestOSPathsSharedToVms); + base::DictionaryValue* shared_paths = update.Get(); + RemovePersistedPathFromPrefs(shared_paths, vm_name, path); } CallSeneschalUnsharePath(vm_name, path, std::move(callback)); @@ -402,63 +426,88 @@ return result; } -std::vector<base::FilePath> CrostiniSharePath::GetPersistedSharedPaths() { +std::vector<base::FilePath> CrostiniSharePath::GetPersistedSharedPaths( + const std::string& vm_name) { std::vector<base::FilePath> result; - PrefService* pref_service = profile_->GetPrefs(); - const base::ListValue* shared_paths = - pref_service->GetList(prefs::kCrostiniSharedPaths); - // Paths in <cryptohome>/Downloads need to be migrated to - // <cryptohome>/MyFiles/Downloads. - bool swap_for_migrate_required = false; - base::ListValue migrated_paths; - for (const auto& shared_path : *shared_paths) { - base::FilePath path(shared_path.GetString()); - base::FilePath migrated; - if (file_manager::util::MigrateFromDownloadsToMyFiles(profile_, path, - &migrated)) { - swap_for_migrate_required = true; - path = migrated; + // |shared_paths| format is {'path': ['vm1', vm2']}. + const base::DictionaryValue* shared_paths = + profile_->GetPrefs()->GetDictionary(prefs::kGuestOSPathsSharedToVms); + for (const auto& it : shared_paths->DictItems()) { + base::FilePath path(it.first); + auto& vms = it.second.GetList(); + for (const auto& vm : vms) { + // Register all shared paths for all VMs since we want FilePathWatchers + // to start immediately. + RegisterSharedPath(vm.GetString(), path); + // Only add to result if path is shared with specified |vm_name|. + if (vm.GetString() == vm_name) { + result.emplace_back(path); + } } - migrated_paths.AppendString(path.value()); - result.emplace_back(path); - RegisterSharedPath(kCrostiniDefaultVmName, path); } - - // If any paths were modified during migration, update prefs. - if (swap_for_migrate_required) { - ListPrefUpdate update(pref_service, crostini::prefs::kCrostiniSharedPaths); - base::ListValue* shared_paths = update.Get(); - shared_paths->Swap(&migrated_paths); - } - return result; } void CrostiniSharePath::SharePersistedPaths( + const std::string& vm_name, base::OnceCallback<void(bool, std::string)> callback) { - SharePaths(kCrostiniDefaultVmName, GetPersistedSharedPaths(), - false /* persist */, std::move(callback)); + SharePaths(vm_name, GetPersistedSharedPaths(vm_name), + /*persist=*/false, std::move(callback)); } -void CrostiniSharePath::RegisterPersistedPath(const base::FilePath& path) { +void CrostiniSharePath::RegisterPersistedPath(const std::string& vm_name, + const base::FilePath& path) { PrefService* pref_service = profile_->GetPrefs(); - ListPrefUpdate update(pref_service, crostini::prefs::kCrostiniSharedPaths); - base::ListValue* shared_paths = update.Get(); - // Check if path exists, remove paths that are children of new path. - bool exists = false; - auto it = shared_paths->begin(); - while (it != shared_paths->end()) { - base::FilePath existing(it->GetString()); - if (path == existing) { - exists = true; - } else if (path.IsParent(existing)) { - it = shared_paths->Erase(it, nullptr); - continue; + DictionaryPrefUpdate update(pref_service, + crostini::prefs::kGuestOSPathsSharedToVms); + base::DictionaryValue* shared_paths = update.Get(); + // Check if path is already shared so we know whether we need to add it. + bool already_shared = false; + // Remove any paths that are children of this path. + // E.g. if path /foo/bar is already shared, and then we share /foo, we + // remove /foo/bar from the list since it will be shared as part of /foo. + std::vector<base::FilePath> children; + for (const auto& it : shared_paths->DictItems()) { + base::FilePath shared(it.first); + auto& vms = it.second.GetList(); + auto vm_matches = + std::find(vms.begin(), vms.end(), base::Value(vm_name)) != vms.end(); + if (path == shared) { + already_shared = true; + if (!vm_matches) { + vms.emplace_back(vm_name); + } + } else if (path.IsParent(shared) && vm_matches) { + children.emplace_back(shared); } - ++it; } - if (!exists) - shared_paths->Append(std::make_unique<base::Value>(path.value())); + for (const auto& child : children) { + RemovePersistedPathFromPrefs(shared_paths, vm_name, child); + } + if (!already_shared) { + base::Value vms(base::Value::Type::LIST); + vms.GetList().emplace_back(base::Value(vm_name)); + shared_paths->SetKey(path.value(), std::move(vms)); + } +} + +void CrostiniSharePath::MigratePersistedPathsToMultiVM( + PrefService* profile_prefs) { + const base::ListValue* shared_paths = + profile_prefs->GetList(prefs::kCrostiniSharedPaths); + if (shared_paths->GetSize() == 0) { + return; + } + // Convert ['foo', 'bar'] to {'foo':['termina'], 'bar':['termina']}. + base::Value dict(base::Value::Type::DICTIONARY); + for (const auto& shared_path : *shared_paths) { + base::Value termina(base::Value::Type::LIST); + termina.GetList().emplace_back(base::Value(kCrostiniDefaultVmName)); + dict.SetKey(shared_path.GetString(), std::move(termina)); + } + profile_prefs->Set(prefs::kGuestOSPathsSharedToVms, std::move(dict)); + + profile_prefs->ClearPref(prefs::kCrostiniSharedPaths); } void CrostiniSharePath::OnVolumeMounted(chromeos::MountError error_code, @@ -467,18 +516,24 @@ return; } - // Fetch list of shared paths even if VM is not running so that - // FilePathWatchers will be added. - auto paths = GetPersistedSharedPaths(); - if (!crostini::CrostiniManager::GetForProfile(profile_)->IsVmRunning( - kCrostiniDefaultVmName)) { - return; - } - for (const auto& path : paths) { - if (path == volume.mount_path() || volume.mount_path().IsParent(path)) { - CallSeneschalSharePath(kCrostiniDefaultVmName, path, false, - base::BindOnce(mount_event_seneschal_callback_, - "share-on-mount", path)); + // Check if any persisted paths match volume.mount_path() or are children + // of it then share them with any running VMs. + const base::DictionaryValue* shared_paths = + profile_->GetPrefs()->GetDictionary(prefs::kGuestOSPathsSharedToVms); + for (const auto& it : shared_paths->DictItems()) { + base::FilePath path(it.first); + if (path != volume.mount_path() && !volume.mount_path().IsParent(path)) { + continue; + } + const auto& vms = it.second.GetList(); + for (const auto& vm : vms) { + RegisterSharedPath(vm.GetString(), path); + if (CrostiniManager::GetForProfile(profile_)->IsVmRunning( + vm.GetString())) { + CallSeneschalSharePath(vm.GetString(), path, false, + base::BindOnce(mount_event_seneschal_callback_, + "share-on-mount", path)); + } } } }
diff --git a/chrome/browser/chromeos/crostini/crostini_share_path.h b/chrome/browser/chromeos/crostini/crostini_share_path.h index 34f648c1..63cad9d 100644 --- a/chrome/browser/chromeos/crostini/crostini_share_path.h +++ b/chrome/browser/chromeos/crostini/crostini_share_path.h
@@ -54,6 +54,12 @@ const base::FilePath& path) = 0; }; + // Migrates from crostini.shared_paths to crostini.paths_shared_to_vms which + // supports multi VM sharing. + // TODO(crbug.com/946273): Remove crostini.shared_paths and migration code + // after M77. + static void MigratePersistedPathsToMultiVM(PrefService* profile_prefs); + static CrostiniSharePath* GetForProfile(Profile* profile); explicit CrostiniSharePath(Profile* profile); ~CrostiniSharePath() override; @@ -88,16 +94,19 @@ // Returns true the first time it is called on this service. bool GetAndSetFirstForSession(); - // Get list of all shared paths for the default crostini container. - std::vector<base::FilePath> GetPersistedSharedPaths(); + // Get list of all shared paths for the specified VM. + std::vector<base::FilePath> GetPersistedSharedPaths( + const std::string& vm_name); - // Share all paths configured in prefs for the default crostini container. + // Share all paths configured in prefs for the specified VM. // Called at container startup. Callback is invoked once complete. void SharePersistedPaths( + const std::string& vm_name, base::OnceCallback<void(bool, std::string)> callback); - // Save |path| into prefs. - void RegisterPersistedPath(const base::FilePath& path); + // Save |path| into prefs for |vm_name|. + void RegisterPersistedPath(const std::string& vm_name, + const base::FilePath& path); // file_manager::VolumeManagerObserver void OnVolumeMounted(chromeos::MountError error_code,
diff --git a/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc b/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc index 2fcc58af..96f11a30 100644 --- a/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc +++ b/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc
@@ -43,6 +43,7 @@ enum class Success { NO, YES }; void SharePathCallback( + const std::string& expected_vm_name, Persist expected_persist, SeneschalClientCalled expected_seneschal_client_called, const vm_tools::seneschal::SharePathRequest::StorageLocation* @@ -53,19 +54,20 @@ const base::FilePath& container_path, bool success, std::string failure_reason) { - const base::ListValue* prefs = - profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths); - std::string share_path; + const base::DictionaryValue* prefs = + profile()->GetPrefs()->GetDictionary(prefs::kGuestOSPathsSharedToVms); + EXPECT_TRUE(prefs->HasKey(shared_path_.value())); + EXPECT_EQ(prefs->FindKey(shared_path_.value())->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey(shared_path_.value())->GetList()[0].GetString(), + kCrostiniDefaultVmName); if (expected_persist == Persist::YES) { - EXPECT_EQ(prefs->GetSize(), 2U); - prefs->GetString(0, &share_path); - EXPECT_EQ(share_path, shared_path_.value()); - prefs->GetString(1, &share_path); - EXPECT_EQ(share_path, share_path_.value()); + EXPECT_EQ(prefs->size(), 2U); + EXPECT_TRUE(prefs->HasKey(share_path_.value())); + EXPECT_EQ(prefs->FindKey(share_path_.value())->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey(share_path_.value())->GetList()[0].GetString(), + expected_vm_name); } else { - EXPECT_EQ(prefs->GetSize(), 1U); - prefs->GetString(0, &share_path); - EXPECT_EQ(share_path, shared_path_.value()); + EXPECT_EQ(prefs->size(), 1U); } EXPECT_EQ(fake_seneschal_client_->share_path_called(), expected_seneschal_client_called == SeneschalClientCalled::YES); @@ -86,6 +88,7 @@ void MountEventSharePathCallback( const std::string& expected_operation, const base::FilePath& expected_path, + const std::string& expected_vm_name, Persist expected_persist, SeneschalClientCalled expected_seneschal_client_called, const vm_tools::seneschal::SharePathRequest::StorageLocation* @@ -100,18 +103,20 @@ std::string failure_reason) { EXPECT_EQ(expected_operation, operation); EXPECT_EQ(expected_path, cros_path); - SharePathCallback(expected_persist, expected_seneschal_client_called, - expected_seneschal_storage_location, - expected_seneschal_path, expected_success, - expected_failure_reason, container_path, success, - failure_reason); + SharePathCallback( + expected_vm_name, expected_persist, expected_seneschal_client_called, + expected_seneschal_storage_location, expected_seneschal_path, + expected_success, expected_failure_reason, container_path, success, + failure_reason); } void SharePersistedPathsCallback(bool success, std::string failure_reason) { EXPECT_TRUE(success); - EXPECT_EQ( - profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths)->GetSize(), - 2U); + EXPECT_EQ(profile() + ->GetPrefs() + ->GetDictionary(prefs::kGuestOSPathsSharedToVms) + ->size(), + 2U); run_loop()->Quit(); } @@ -133,12 +138,12 @@ const std::string& expected_failure_reason, bool success, std::string failure_reason) { - const base::ListValue* prefs = - profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths); + const base::DictionaryValue* prefs = + profile()->GetPrefs()->GetDictionary(prefs::kGuestOSPathsSharedToVms); if (expected_persist == Persist::YES) { - EXPECT_NE(prefs->Find(base::Value(path.value())), prefs->end()); + EXPECT_TRUE(prefs->HasKey(path.value())); } else { - EXPECT_EQ(prefs->Find(base::Value(path.value())), prefs->end()); + EXPECT_FALSE(prefs->HasKey(path.value())); } EXPECT_EQ(fake_seneschal_client_->unshare_path_called(), expected_seneschal_client_called == SeneschalClientCalled::YES); @@ -198,10 +203,12 @@ root_ = file_manager::util::GetMyFilesFolderForProfile(profile()); share_path_ = root_.Append("path-to-share"); shared_path_ = root_.Append("already-shared"); - ListPrefUpdate update(profile()->GetPrefs(), - crostini::prefs::kCrostiniSharedPaths); - base::ListValue* shared_paths = update.Get(); - shared_paths->Append(std::make_unique<base::Value>(shared_path_.value())); + DictionaryPrefUpdate update(profile()->GetPrefs(), + prefs::kGuestOSPathsSharedToVms); + base::DictionaryValue* shared_paths = update.Get(); + base::Value termina(base::Value::Type::LIST); + termina.GetList().emplace_back(base::Value(kCrostiniDefaultVmName)); + shared_paths->SetKey(shared_path_.value(), std::move(termina)); volume_downloads_ = file_manager::Volume::CreateForDownloads(root_); crostini_share_path_->RegisterSharedPath(kCrostiniDefaultVmName, shared_path_); @@ -210,7 +217,7 @@ void SetUp() override { run_loop_ = std::make_unique<base::RunLoop>(); profile_ = std::make_unique<TestingProfile>(); - crostini_share_path_ = std::make_unique<CrostiniSharePath>(profile()); + crostini_share_path_ = CrostiniSharePath::GetForProfile(profile()); crostini_share_path_->set_no_file_watchers_for_testing(); // Setup for DriveFS. @@ -243,9 +250,6 @@ protected: base::RunLoop* run_loop() { return run_loop_.get(); } Profile* profile() { return profile_.get(); } - CrostiniSharePath* crostini_share_path() { - return crostini_share_path_.get(); - } base::FilePath root_; base::FilePath share_path_; base::FilePath shared_path_; @@ -259,7 +263,7 @@ std::unique_ptr<base::RunLoop> run_loop_; // run_loop_ must be created on the UI thread. std::unique_ptr<TestingProfile> profile_; - std::unique_ptr<CrostiniSharePath> crostini_share_path_; + CrostiniSharePath* crostini_share_path_; base::test::ScopedFeatureList features_; std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; AccountId account_id_; @@ -272,10 +276,10 @@ TEST_F(CrostiniSharePathTest, SuccessDownloadsRoot) { features_.InitWithFeatures({}, {chromeos::features::kMyFilesVolume}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", root_, PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::DOWNLOADS, "", Success::YES, "")); @@ -287,10 +291,10 @@ SetUpVolume(); base::FilePath my_files = file_manager::util::GetMyFilesFolderForProfile(profile()); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", my_files, PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::MY_FILES, "", Success::YES, "")); @@ -300,10 +304,10 @@ TEST_F(CrostiniSharePathTest, SuccessNoPersist) { features_.InitWithFeatures({chromeos::features::kMyFilesVolume}, {}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", share_path_, PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::MY_FILES, "path-to-share", Success::YES, "")); @@ -313,10 +317,10 @@ TEST_F(CrostiniSharePathTest, SuccessPersist) { features_.InitWithFeatures({chromeos::features::kMyFilesVolume}, {}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", share_path_, PERSIST_YES, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::YES, + base::Unretained(this), "vm-running", Persist::YES, SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::MY_FILES, "path-to-share", Success::YES, "")); @@ -326,10 +330,10 @@ TEST_F(CrostiniSharePathTest, SuccessDriveFsMyDrive) { features_.InitWithFeatures({chromeos::features::kDriveFs}, {}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", drivefs_.Append("root").Append("my"), PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::DRIVEFS_MY_DRIVE, "my", Success::YES, "")); @@ -339,10 +343,10 @@ TEST_F(CrostiniSharePathTest, FailureDriveFsDisabled) { features_.InitWithFeatures({}, {chromeos::features::kDriveFs}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", drivefs_.Append("root").Append("my"), PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::NO, nullptr, "my", Success::NO, "Path is not allowed")); run_loop()->Run(); @@ -351,10 +355,10 @@ TEST_F(CrostiniSharePathTest, SuccessDriveFsMyDriveRoot) { features_.InitWithFeatures({chromeos::features::kDriveFs}, {}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", drivefs_.Append("root"), PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::DRIVEFS_MY_DRIVE, "", Success::YES, "")); @@ -364,10 +368,10 @@ TEST_F(CrostiniSharePathTest, FailDriveFsRoot) { features_.InitWithFeatures({chromeos::features::kDriveFs}, {}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", drivefs_, PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::NO, nullptr, "", Success::NO, "Path is not allowed")); run_loop()->Run(); @@ -376,11 +380,11 @@ TEST_F(CrostiniSharePathTest, SuccessDriveFsTeamDrives) { features_.InitWithFeatures({chromeos::features::kDriveFs}, {}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", drivefs_.Append("team_drives").Append("team"), PERSIST_NO, base::BindOnce( &CrostiniSharePathTest::SharePathCallback, base::Unretained(this), - Persist::NO, SeneschalClientCalled::YES, + "vm-running", Persist::NO, SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::DRIVEFS_TEAM_DRIVES, "team", Success::YES, "")); run_loop()->Run(); @@ -390,10 +394,10 @@ TEST_F(CrostiniSharePathTest, DISABLED_SuccessDriveFsComputersGrandRoot) { features_.InitWithFeatures({chromeos::features::kDriveFs}, {}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", drivefs_.Append("Computers"), PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::DRIVEFS_COMPUTERS, "pc", Success::YES, "")); @@ -404,10 +408,10 @@ TEST_F(CrostiniSharePathTest, Bug917920DriveFsComputersGrandRoot) { features_.InitWithFeatures({chromeos::features::kDriveFs}, {}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", drivefs_.Append("Computers"), PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::NO, nullptr, "", Success::NO, "Path is not allowed")); run_loop()->Run(); @@ -417,10 +421,10 @@ TEST_F(CrostiniSharePathTest, DISABLED_SuccessDriveFsComputerRoot) { features_.InitWithFeatures({chromeos::features::kDriveFs}, {}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", drivefs_.Append("Computers").Append("pc"), PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::DRIVEFS_COMPUTERS, "pc", Success::YES, "")); @@ -431,10 +435,10 @@ TEST_F(CrostiniSharePathTest, Bug917920DriveFsComputerRoot) { features_.InitWithFeatures({chromeos::features::kDriveFs}, {}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", drivefs_.Append("Computers").Append("pc"), PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::NO, nullptr, "", Success::NO, "Path is not allowed")); run_loop()->Run(); @@ -443,12 +447,12 @@ TEST_F(CrostiniSharePathTest, SuccessDriveFsComputersLevel3) { features_.InitWithFeatures({chromeos::features::kDriveFs}, {}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", drivefs_.Append("Computers").Append("pc").Append("SyncFolder"), PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::DRIVEFS_COMPUTERS, "pc/SyncFolder", Success::YES, "")); @@ -458,11 +462,11 @@ TEST_F(CrostiniSharePathTest, FailDriveFsTrash) { features_.InitWithFeatures({chromeos::features::kDriveFs}, {}); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", drivefs_.Append(".Trash").Append("in-the-trash"), PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::NO, nullptr, "", Success::NO, "Path is not allowed")); run_loop()->Run(); @@ -470,10 +474,10 @@ TEST_F(CrostiniSharePathTest, SuccessRemovable) { SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", base::FilePath("/media/removable/MyUSB"), PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::REMOVABLE, "MyUSB", Success::YES, "")); @@ -482,10 +486,10 @@ TEST_F(CrostiniSharePathTest, FailRemovableRoot) { SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", base::FilePath("/media/removable"), PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::NO, nullptr, "", Success::NO, "Path is not allowed")); run_loop()->Run(); @@ -506,10 +510,10 @@ share_path_response.set_failure_reason("test failure"); fake_seneschal_client_->set_share_path_response(share_path_response); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "error-seneschal", share_path_, PERSIST_YES, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::YES, + base::Unretained(this), "error-seneschal", Persist::YES, SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::MY_FILES, "path-to-share", Success::NO, "test failure")); @@ -519,10 +523,10 @@ TEST_F(CrostiniSharePathTest, SharePathErrorPathNotAbsolute) { SetUpVolume(); const base::FilePath path("not/absolute/dir"); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", path, PERSIST_YES, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::NO, nullptr, "", Success::NO, "Path must be absolute")); run_loop()->Run(); @@ -531,10 +535,10 @@ TEST_F(CrostiniSharePathTest, SharePathErrorReferencesParent) { SetUpVolume(); const base::FilePath path("/path/../references/parent"); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", path, PERSIST_NO, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::NO, nullptr, "", Success::NO, "Path must be absolute")); run_loop()->Run(); @@ -543,10 +547,10 @@ TEST_F(CrostiniSharePathTest, SharePathErrorNotUnderDownloads) { SetUpVolume(); const base::FilePath path("/not/under/downloads"); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-running", path, PERSIST_YES, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::NO, + base::Unretained(this), "vm-running", Persist::NO, SeneschalClientCalled::NO, nullptr, "", Success::NO, "Path is not allowed")); run_loop()->Run(); @@ -557,10 +561,10 @@ {chromeos::features::kMyFilesVolume, features::kCrostini}, {}); GetFakeUserManager()->LoginUser(account_id_); SetUpVolume(); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "vm-to-be-started", share_path_, PERSIST_YES, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::YES, + base::Unretained(this), "vm-to-be-started", Persist::YES, SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::MY_FILES, "path-to-share", Success::YES, "")); @@ -573,12 +577,12 @@ start_vm_response.set_status(vm_tools::concierge::VM_STATUS_FAILURE); fake_concierge_client_->set_start_vm_response(start_vm_response); - crostini_share_path()->SharePath( + crostini_share_path_->SharePath( "error-vm-could-not-be-started", share_path_, PERSIST_YES, base::BindOnce(&CrostiniSharePathTest::SharePathCallback, - base::Unretained(this), Persist::YES, - SeneschalClientCalled::NO, nullptr, "", Success::NO, - "VM could not be started")); + base::Unretained(this), "error-vm-could-not-be-started", + Persist::YES, SeneschalClientCalled::NO, nullptr, "", + Success::NO, "VM could not be started")); run_loop()->Run(); } @@ -588,85 +592,103 @@ ASSERT_TRUE(base::CreateDirectory(share_path2_)); CrostiniManager::GetForProfile(profile())->AddRunningVmForTesting( kCrostiniDefaultVmName); - base::ListValue shared_paths = base::ListValue(); - shared_paths.GetList().push_back(base::Value(share_path_.value())); - shared_paths.GetList().push_back(base::Value(share_path2_.value())); - profile()->GetPrefs()->Set(prefs::kCrostiniSharedPaths, shared_paths); - crostini_share_path()->SharePersistedPaths( + base::Value shared_paths(base::Value::Type::DICTIONARY); + base::Value vms(base::Value::Type::LIST); + vms.GetList().emplace_back(base::Value(kCrostiniDefaultVmName)); + shared_paths.SetKey(share_path_.value(), std::move(vms)); + base::Value vms2(base::Value::Type::LIST); + vms2.GetList().emplace_back(base::Value(kCrostiniDefaultVmName)); + shared_paths.SetKey(share_path2_.value(), std::move(vms2)); + profile()->GetPrefs()->Set(prefs::kGuestOSPathsSharedToVms, shared_paths); + crostini_share_path_->SharePersistedPaths( + kCrostiniDefaultVmName, base::BindOnce(&CrostiniSharePathTest::SharePersistedPathsCallback, base::Unretained(this))); run_loop()->Run(); } TEST_F(CrostiniSharePathTest, RegisterPersistedPaths) { - base::ListValue shared_paths = base::ListValue(); + base::Value shared_paths(base::Value::Type::DICTIONARY); SetUpVolume(); - profile()->GetPrefs()->Set(prefs::kCrostiniSharedPaths, shared_paths); + profile()->GetPrefs()->Set(prefs::kGuestOSPathsSharedToVms, shared_paths); - crostini_share_path()->RegisterPersistedPath(base::FilePath("/a/a/a")); - const base::ListValue* prefs = - profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths); - EXPECT_EQ(prefs->GetSize(), 1U); - std::string path; - prefs->GetString(0, &path); - EXPECT_EQ(path, "/a/a/a"); + crostini_share_path_->RegisterPersistedPath("v1", base::FilePath("/a/a/a")); + const base::DictionaryValue* prefs = + profile()->GetPrefs()->GetDictionary(prefs::kGuestOSPathsSharedToVms); + EXPECT_EQ(prefs->size(), 1U); + EXPECT_EQ(prefs->FindKey("/a/a/a")->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey("/a/a/a")->GetList()[0].GetString(), "v1"); - // Adding the same path again should not cause any changes. - crostini_share_path()->RegisterPersistedPath(base::FilePath("/a/a/a")); - EXPECT_EQ(prefs->GetSize(), 1U); - prefs->GetString(0, &path); - EXPECT_EQ(path, "/a/a/a"); + // Adding the same path again for same VM should not cause any changes. + crostini_share_path_->RegisterPersistedPath("v1", base::FilePath("/a/a/a")); + prefs = profile()->GetPrefs()->GetDictionary(prefs::kGuestOSPathsSharedToVms); + EXPECT_EQ(prefs->size(), 1U); + EXPECT_EQ(prefs->FindKey("/a/a/a")->GetList().size(), 1U); + + // Adding the same path for a new VM adds to the vm list. + crostini_share_path_->RegisterPersistedPath("v2", base::FilePath("/a/a/a")); + EXPECT_EQ(prefs->size(), 1U); + EXPECT_EQ(prefs->FindKey("/a/a/a")->GetList().size(), 2U); + EXPECT_EQ(prefs->FindKey("/a/a/a")->GetList()[0].GetString(), "v1"); + EXPECT_EQ(prefs->FindKey("/a/a/a")->GetList()[1].GetString(), "v2"); // Add more paths. - crostini_share_path()->RegisterPersistedPath(base::FilePath("/a/a/b")); - crostini_share_path()->RegisterPersistedPath(base::FilePath("/a/a/c")); - crostini_share_path()->RegisterPersistedPath(base::FilePath("/a/b/a")); - crostini_share_path()->RegisterPersistedPath(base::FilePath("/b/a/a")); - prefs = profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths); - EXPECT_EQ(prefs->GetSize(), 5U); - prefs->GetString(0, &path); - EXPECT_EQ(path, "/a/a/a"); - prefs->GetString(1, &path); - EXPECT_EQ(path, "/a/a/b"); - prefs->GetString(2, &path); - EXPECT_EQ(path, "/a/a/c"); - prefs->GetString(3, &path); - EXPECT_EQ(path, "/a/b/a"); - prefs->GetString(4, &path); - EXPECT_EQ(path, "/b/a/a"); + crostini_share_path_->RegisterPersistedPath("v1", base::FilePath("/a/a/b")); + crostini_share_path_->RegisterPersistedPath("v1", base::FilePath("/a/a/c")); + crostini_share_path_->RegisterPersistedPath("v1", base::FilePath("/a/b/a")); + crostini_share_path_->RegisterPersistedPath("v1", base::FilePath("/b/a/a")); + EXPECT_EQ(prefs->size(), 5U); + EXPECT_EQ(prefs->FindKey("/a/a/a")->GetList().size(), 2U); + EXPECT_EQ(prefs->FindKey("/a/a/b")->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey("/a/a/c")->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey("/a/b/a")->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey("/b/a/a")->GetList().size(), 1U); - // Adding /a/a should remove /a/a/b, /a/a/c. - crostini_share_path()->RegisterPersistedPath(base::FilePath("/a/a")); - prefs = profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths); - EXPECT_EQ(prefs->GetSize(), 3U); - prefs->GetString(0, &path); - EXPECT_EQ(path, "/a/b/a"); - prefs->GetString(1, &path); - EXPECT_EQ(path, "/b/a/a"); - prefs->GetString(2, &path); - EXPECT_EQ(path, "/a/a"); + // Adding /a/a should remove /a/a/a, /a/a/b, /a/a/c. + crostini_share_path_->RegisterPersistedPath("v1", base::FilePath("/a/a")); + EXPECT_EQ(prefs->size(), 4U); + EXPECT_EQ(prefs->FindKey("/a/a/a")->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey("/a/a/a")->GetList()[0].GetString(), "v2"); + EXPECT_EQ(prefs->FindKey("/a/b/a")->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey("/b/a/a")->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey("/a/a")->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey("/a/a")->GetList()[0].GetString(), "v1"); // Adding /a should remove /a/a, /a/b/a. - crostini_share_path()->RegisterPersistedPath(base::FilePath("/a")); - prefs = profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths); - EXPECT_EQ(prefs->GetSize(), 2U); - prefs->GetString(0, &path); - EXPECT_EQ(path, "/b/a/a"); - prefs->GetString(1, &path); - EXPECT_EQ(path, "/a"); + crostini_share_path_->RegisterPersistedPath("v1", base::FilePath("/a")); + EXPECT_EQ(prefs->size(), 3U); + EXPECT_EQ(prefs->FindKey("/a/a/a")->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey("/a/a/a")->GetList()[0].GetString(), "v2"); + EXPECT_EQ(prefs->FindKey("/b/a/a")->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey("/a")->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey("/a")->GetList()[0].GetString(), "v1"); // Adding / should remove all others. - crostini_share_path()->RegisterPersistedPath(base::FilePath("/")); - prefs = profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths); - EXPECT_EQ(prefs->GetSize(), 1U); - prefs->GetString(0, &path); - EXPECT_EQ(path, "/"); + crostini_share_path_->RegisterPersistedPath("v1", base::FilePath("/")); + EXPECT_EQ(prefs->size(), 2U); + EXPECT_EQ(prefs->FindKey("/a/a/a")->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey("/a/a/a")->GetList()[0].GetString(), "v2"); + EXPECT_EQ(prefs->FindKey("/")->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey("/")->GetList()[0].GetString(), "v1"); + + // Add / for v2. + crostini_share_path_->RegisterPersistedPath("v2", base::FilePath("/")); + EXPECT_EQ(prefs->size(), 1U); + EXPECT_EQ(prefs->FindKey("/")->GetList().size(), 2U); + EXPECT_EQ(prefs->FindKey("/")->GetList()[0].GetString(), "v1"); + EXPECT_EQ(prefs->FindKey("/")->GetList()[1].GetString(), "v2"); } TEST_F(CrostiniSharePathTest, UnsharePathSuccess) { features_.InitWithFeatures({chromeos::features::kMyFilesVolume}, {}); SetUpVolume(); - crostini_share_path()->UnsharePath( + DictionaryPrefUpdate update(profile()->GetPrefs(), + prefs::kGuestOSPathsSharedToVms); + base::DictionaryValue* shared_paths = update.Get(); + base::Value vms(base::Value::Type::LIST); + vms.GetList().emplace_back(base::Value("vm-running")); + shared_paths->SetKey(shared_path_.value(), std::move(vms)); + crostini_share_path_->UnsharePath( "vm-running", shared_path_, true, base::BindOnce(&CrostiniSharePathTest::UnsharePathCallback, base::Unretained(this), shared_path_, Persist::NO, @@ -678,7 +700,7 @@ TEST_F(CrostiniSharePathTest, UnsharePathRoot) { features_.InitWithFeatures({chromeos::features::kMyFilesVolume}, {}); SetUpVolume(); - crostini_share_path()->UnsharePath( + crostini_share_path_->UnsharePath( "vm-running", root_, true, base::BindOnce(&CrostiniSharePathTest::UnsharePathCallback, base::Unretained(this), root_, Persist::NO, @@ -688,7 +710,13 @@ TEST_F(CrostiniSharePathTest, UnsharePathVmNotRunning) { SetUpVolume(); - crostini_share_path()->UnsharePath( + DictionaryPrefUpdate update(profile()->GetPrefs(), + prefs::kGuestOSPathsSharedToVms); + base::DictionaryValue* shared_paths = update.Get(); + base::Value vms(base::Value::Type::LIST); + vms.GetList().emplace_back(base::Value("vm-not-running")); + shared_paths->SetKey(shared_path_.value(), std::move(vms)); + crostini_share_path_->UnsharePath( "vm-not-running", shared_path_, true, base::BindOnce(&CrostiniSharePathTest::UnsharePathCallback, base::Unretained(this), shared_path_, Persist::NO, @@ -700,7 +728,7 @@ TEST_F(CrostiniSharePathTest, UnsharePathInvalidPath) { SetUpVolume(); base::FilePath invalid("invalid/path"); - crostini_share_path()->UnsharePath( + crostini_share_path_->UnsharePath( "vm-running", invalid, true, base::BindOnce(&CrostiniSharePathTest::UnsharePathCallback, base::Unretained(this), invalid, Persist::NO, @@ -709,58 +737,72 @@ run_loop()->Run(); } -TEST_F(CrostiniSharePathTest, GetPersistedSharedPaths) { +TEST_F(CrostiniSharePathTest, MigratePersistedPathsToMultiVM) { SetUpVolume(); base::ListValue shared_paths = base::ListValue(); base::FilePath downloads_file = profile()->GetPath().Append("Downloads/file"); shared_paths.AppendString(downloads_file.value()); base::FilePath not_downloads("/not/downloads"); shared_paths.AppendString(not_downloads.value()); - std::string prefstr; - // MyFilesVolume disabled. - // Return prefs unchanged. - { - base::test::ScopedFeatureList features; - features.InitWithFeatures({}, {chromeos::features::kMyFilesVolume}); - storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem( - file_manager::util::GetDownloadsMountPointName(profile())); - profile()->GetPrefs()->Set(prefs::kCrostiniSharedPaths, shared_paths); - std::vector<base::FilePath> paths = - crostini_share_path()->GetPersistedSharedPaths(); - EXPECT_EQ(paths.size(), 2U); - EXPECT_EQ(paths[0], downloads_file); - EXPECT_EQ(paths[1], not_downloads); - const base::ListValue* prefs = - profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths); - EXPECT_EQ(prefs->GetSize(), 2U); - prefs->GetString(0, &prefstr); - EXPECT_EQ(prefstr, downloads_file.value()); - prefs->GetString(1, &prefstr); - EXPECT_EQ(prefstr, not_downloads.value()); - } - // MyFilesVolume enabled. - // Migrate prefs and return. - { - base::test::ScopedFeatureList features; - features.InitWithFeatures({chromeos::features::kMyFilesVolume}, {}); - storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem( - file_manager::util::GetDownloadsMountPointName(profile())); - profile()->GetPrefs()->Set(prefs::kCrostiniSharedPaths, shared_paths); - base::FilePath myfiles_file = - profile()->GetPath().Append("MyFiles/Downloads/file"); - std::vector<base::FilePath> paths = - crostini_share_path()->GetPersistedSharedPaths(); - EXPECT_EQ(paths.size(), 2U); - EXPECT_EQ(paths[0], myfiles_file); - EXPECT_EQ(paths[1], not_downloads); - const base::ListValue* prefs = - profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths); - EXPECT_EQ(prefs->GetSize(), 2U); - prefs->GetString(0, &prefstr); - EXPECT_EQ(prefstr, myfiles_file.value()); - prefs->GetString(1, &prefstr); - EXPECT_EQ(prefstr, not_downloads.value()); - } + profile()->GetPrefs()->Set(prefs::kCrostiniSharedPaths, shared_paths); + CrostiniSharePath::MigratePersistedPathsToMultiVM(profile()->GetPrefs()); + EXPECT_EQ( + profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths)->GetSize(), + 0U); + const base::DictionaryValue* prefs = + profile()->GetPrefs()->GetDictionary(prefs::kGuestOSPathsSharedToVms); + EXPECT_EQ(prefs->size(), 2U); + EXPECT_EQ(prefs->FindKey(downloads_file.value())->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey(downloads_file.value())->GetList()[0].GetString(), + "termina"); + EXPECT_EQ(prefs->FindKey(not_downloads.value())->GetList().size(), 1U); + EXPECT_EQ(prefs->FindKey(not_downloads.value())->GetList()[0].GetString(), + "termina"); +} + +TEST_F(CrostiniSharePathTest, GetPersistedSharedPaths) { + SetUpVolume(); + // path1:['vm1'], path2:['vm2'], path3:['vm3'], path12:['vm1','vm2'] + base::Value shared_paths(base::Value::Type::DICTIONARY); + + base::FilePath path1("path1"); + base::Value path1vms(base::Value::Type::LIST); + path1vms.GetList().emplace_back(base::Value("vm1")); + shared_paths.SetKey(path1.value(), std::move(path1vms)); + base::FilePath path2("path2"); + base::Value path2vms(base::Value::Type::LIST); + path2vms.GetList().emplace_back(base::Value("vm2")); + shared_paths.SetKey(path2.value(), std::move(path2vms)); + base::FilePath path3("path3"); + base::Value path3vms(base::Value::Type::LIST); + path3vms.GetList().emplace_back(base::Value("vm3")); + shared_paths.SetKey(path3.value(), std::move(path3vms)); + base::FilePath path12("path12"); + base::Value path12vms(base::Value::Type::LIST); + path12vms.GetList().emplace_back(base::Value("vm1")); + path12vms.GetList().emplace_back(base::Value("vm2")); + shared_paths.SetKey(path12.value(), std::move(path12vms)); + profile()->GetPrefs()->Set(prefs::kGuestOSPathsSharedToVms, shared_paths); + + std::vector<base::FilePath> paths = + crostini_share_path_->GetPersistedSharedPaths("vm1"); + std::sort(paths.begin(), paths.end()); + EXPECT_EQ(paths.size(), 2U); + EXPECT_EQ(paths[0], path1); + EXPECT_EQ(paths[1], path12); + + paths = crostini_share_path_->GetPersistedSharedPaths("vm2"); + std::sort(paths.begin(), paths.end()); + EXPECT_EQ(paths.size(), 2U); + EXPECT_EQ(paths[0], path12); + EXPECT_EQ(paths[1], path2); + + paths = crostini_share_path_->GetPersistedSharedPaths("vm3"); + EXPECT_EQ(paths.size(), 1U); + EXPECT_EQ(paths[0], path3); + + paths = crostini_share_path_->GetPersistedSharedPaths("vm4"); + EXPECT_EQ(paths.size(), 0U); } TEST_F(CrostiniSharePathTest, ShareOnMountSuccessParentMount) { @@ -771,7 +813,8 @@ crostini_share_path_->set_mount_event_seneschal_callback_for_testing( base::BindRepeating(&CrostiniSharePathTest::MountEventSharePathCallback, base::Unretained(this), "share-on-mount", - shared_path_, Persist::NO, SeneschalClientCalled::YES, + shared_path_, kCrostiniDefaultVmName, Persist::NO, + SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::MY_FILES, "already-shared", Success::YES, "")); crostini_share_path_->OnVolumeMounted(chromeos::MountError::MOUNT_ERROR_NONE, @@ -789,7 +832,8 @@ crostini_share_path_->set_mount_event_seneschal_callback_for_testing( base::BindRepeating(&CrostiniSharePathTest::MountEventSharePathCallback, base::Unretained(this), "share-on-mount", - shared_path_, Persist::NO, SeneschalClientCalled::YES, + shared_path_, kCrostiniDefaultVmName, Persist::NO, + SeneschalClientCalled::YES, &vm_tools::seneschal::SharePathRequest::MY_FILES, "already-shared", Success::YES, "")); crostini_share_path_->OnVolumeMounted(chromeos::MountError::MOUNT_ERROR_NONE,
diff --git a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc index d0d0a71..58acedc 100644 --- a/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc +++ b/chrome/browser/chromeos/extensions/file_manager/file_manager_private_apitest.cc
@@ -556,7 +556,7 @@ storage::ExternalMountPoints::GetSystemInstance()->GetRegisteredPath( file_manager::util::GetDownloadsMountPointName(browser()->profile()), &downloads)); - // Setup prefs crostini.shared_paths. + // Setup prefs guest_os.paths_shared_to_vms. base::FilePath shared1 = downloads.AppendASCII("shared1"); base::FilePath shared2 = downloads.AppendASCII("shared2"); { @@ -565,11 +565,12 @@ ASSERT_TRUE(base::CreateDirectory(shared1)); ASSERT_TRUE(base::CreateDirectory(shared2)); } - base::ListValue shared_paths; - shared_paths.AppendString(shared1.value()); - shared_paths.AppendString(shared2.value()); - browser()->profile()->GetPrefs()->Set(crostini::prefs::kCrostiniSharedPaths, - shared_paths); + crostini::CrostiniSharePath* crostini_share_path = + crostini::CrostiniSharePath::GetForProfile(browser()->profile()); + crostini_share_path->RegisterPersistedPath(crostini::kCrostiniDefaultVmName, + shared1); + crostini_share_path->RegisterPersistedPath(crostini::kCrostiniDefaultVmName, + shared2); ASSERT_TRUE(RunComponentExtensionTest("file_browser/crostini_test")); }
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc index 48617d3..befea28 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
@@ -746,7 +746,8 @@ crostini::CrostiniSharePath::GetForProfile(profile); bool first_for_session = params->observe_first_for_session && crostini_share_path->GetAndSetFirstForSession(); - auto shared_paths = crostini_share_path->GetPersistedSharedPaths(); + auto shared_paths = crostini_share_path->GetPersistedSharedPaths( + crostini::kCrostiniDefaultVmName); auto entries = std::make_unique<base::ListValue>(); for (const base::FilePath& path : shared_paths) { std::string mount_name;
diff --git a/chrome/browser/chromeos/network_change_manager_client.cc b/chrome/browser/chromeos/network_change_manager_client.cc index f64f37f..c3800e7c 100644 --- a/chrome/browser/chromeos/network_change_manager_client.cc +++ b/chrome/browser/chromeos/network_change_manager_client.cc
@@ -12,6 +12,7 @@ #include "chromeos/network/network_state_handler.h" #include "content/public/browser/network_service_instance.h" #include "content/public/common/network_service_util.h" +#include "net/base/network_change_notifier.h" #include "net/base/network_change_notifier_posix.h" #include "services/network/public/mojom/network_service.mojom.h" @@ -19,8 +20,8 @@ NetworkChangeManagerClient::NetworkChangeManagerClient( net::NetworkChangeNotifierPosix* network_change_notifier) - : connection_type_(net::NetworkChangeNotifier::CONNECTION_NONE), - connection_subtype_(net::NetworkChangeNotifier::SUBTYPE_NONE), + : connection_type_(net::NetworkChangeNotifier::GetConnectionType()), + connection_subtype_(net::NetworkChangeNotifier::GetConnectionSubtype()), network_change_notifier_(network_change_notifier) { PowerManagerClient::Get()->AddObserver(this); NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
diff --git a/chrome/browser/chromeos/network_change_manager_client.h b/chrome/browser/chromeos/network_change_manager_client.h index 9731798..36cc507f 100644 --- a/chrome/browser/chromeos/network_change_manager_client.h +++ b/chrome/browser/chromeos/network_change_manager_client.h
@@ -42,6 +42,8 @@ friend class NetworkChangeManagerClientUpdateTest; FRIEND_TEST_ALL_PREFIXES(NetworkChangeManagerClientTest, ConnectionTypeFromShill); + FRIEND_TEST_ALL_PREFIXES(NetworkChangeManagerClientTest, + NetworkChangeNotifierConnectionTypeUpdated); void ConnectToNetworkChangeManager(); void ReconnectToNetworkChangeManager();
diff --git a/chrome/browser/chromeos/network_change_manager_client_unittest.cc b/chrome/browser/chromeos/network_change_manager_client_unittest.cc index 23e42a6..a2576eb6 100644 --- a/chrome/browser/chromeos/network_change_manager_client_unittest.cc +++ b/chrome/browser/chromeos/network_change_manager_client_unittest.cc
@@ -12,6 +12,7 @@ #include "base/strings/string_split.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/power/power_manager_client.h" +#include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/network/network_handler.h" #include "chromeos/network/network_state.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -106,6 +107,43 @@ } } +TEST(NetworkChangeManagerClientTest, + NetworkChangeNotifierConnectionTypeUpdated) { + // Create a NetworkChangeNotifier with a non-NONE connection type. + content::TestBrowserThreadBundle thread_bundle_; + std::unique_ptr<net::NetworkChangeNotifierPosix> network_change_notifier( + static_cast<net::NetworkChangeNotifierPosix*>( + net::NetworkChangeNotifier::Create())); + network_change_notifier->OnConnectionChanged( + net::NetworkChangeNotifier::CONNECTION_UNKNOWN); + EXPECT_EQ(net::NetworkChangeNotifier::CONNECTION_UNKNOWN, + net::NetworkChangeNotifier::GetConnectionType()); + + // Initialize DBus and clear services so NetworkHandler thinks we're offline. + DBusThreadManager::Initialize(); + PowerManagerClient::InitializeFake(); + NetworkHandler::Initialize(); + DBusThreadManager::Get() + ->GetShillServiceClient() + ->GetTestInterface() + ->ClearServices(); + + auto client = std::make_unique<NetworkChangeManagerClient>( + network_change_notifier.get()); + + // NetworkChangeManagerClient should have read the network state from DBus + // and notified NetworkChangeNotifier that we're offline. + EXPECT_EQ(net::NetworkChangeNotifier::CONNECTION_NONE, + client->connection_type_); + EXPECT_EQ(net::NetworkChangeNotifier::CONNECTION_NONE, + net::NetworkChangeNotifier::GetConnectionType()); + + client.reset(); + NetworkHandler::Shutdown(); + PowerManagerClient::Shutdown(); + DBusThreadManager::Shutdown(); +} + class NetworkChangeManagerClientUpdateTest : public testing::Test { protected: NetworkChangeManagerClientUpdateTest() : default_network_("") {}
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 57bac8d..8033e9e 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -371,8 +371,8 @@ // Crostini (*s_whitelist)[crostini::prefs::kCrostiniEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN; - (*s_whitelist)[crostini::prefs::kCrostiniSharedPaths] = - settings_api::PrefType::PREF_TYPE_LIST; + (*s_whitelist)[crostini::prefs::kGuestOSPathsSharedToVms] = + settings_api::PrefType::PREF_TYPE_DICTIONARY; (*s_whitelist)[crostini::prefs::kCrostiniSharedUsbDevices] = settings_api::PrefType::PREF_TYPE_LIST; (*s_whitelist)[crostini::prefs::kCrostiniContainers] =
diff --git a/chrome/browser/extensions/convert_web_app.cc b/chrome/browser/extensions/convert_web_app.cc index ce49f80..c47b89d 100644 --- a/chrome/browser/extensions/convert_web_app.cc +++ b/chrome/browser/extensions/convert_web_app.cc
@@ -36,6 +36,7 @@ #include "extensions/common/file_util.h" #include "extensions/common/image_util.h" #include "extensions/common/manifest_constants.h" +#include "extensions/common/manifest_handlers/file_handler_info.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/color_utils.h" @@ -49,6 +50,45 @@ namespace { const char kIconsDirName[] = "icons"; const char kScopeUrlHandlerId[] = "scope"; + +std::unique_ptr<base::DictionaryValue> CreateFileHandlersForBookmarkApp( + blink::Manifest::FileHandler file_handler) { + base::Value file_handlers(base::Value::Type::DICTIONARY); + + for (const auto& handler : file_handler) { + base::Value file_handler(base::Value::Type::DICTIONARY); + file_handler.SetKey(keys::kFileHandlerIncludeDirectories, + base::Value(false)); + file_handler.SetKey(keys::kFileHandlerVerb, + base::Value(extensions::file_handler_verbs::kOpenWith)); + + base::Value mime_types(base::Value::Type::LIST); + base::Value file_extensions(base::Value::Type::LIST); + + for (const auto& acceptsUTF16 : handler.accept) { + std::string acceptsUTF8 = base::UTF16ToUTF8(acceptsUTF16); + if (acceptsUTF8.size() == 0) + continue; + + if (acceptsUTF8[0] == '.') { + file_extensions.GetList().push_back(base::Value(acceptsUTF8.substr(1))); + } else { + mime_types.GetList().push_back(base::Value(acceptsUTF8)); + } + } + + file_handler.SetKey(keys::kFileHandlerTypes, std::move(mime_types)); + file_handler.SetKey(keys::kFileHandlerExtensions, + std::move(file_extensions)); + + file_handlers.SetKey(base::UTF16ToUTF8(handler.name), + std::move(file_handler)); + } + + return base::DictionaryValue::From( + base::Value::ToUniquePtrValue(std::move(file_handlers))); +} + } // namespace std::unique_ptr<base::DictionaryValue> CreateURLHandlersForBookmarkApp( @@ -162,6 +202,11 @@ web_app.scope, web_app.title)); } + if (web_app.file_handler) { + root->SetDictionary(keys::kFileHandlers, CreateFileHandlersForBookmarkApp( + web_app.file_handler.value())); + } + // Add the icons and linked icon information. auto icons = std::make_unique<base::DictionaryValue>(); auto linked_icons = std::make_unique<base::ListValue>();
diff --git a/chrome/browser/extensions/convert_web_app_unittest.cc b/chrome/browser/extensions/convert_web_app_unittest.cc index 6ff1e4e..25638de3 100644 --- a/chrome/browser/extensions/convert_web_app_unittest.cc +++ b/chrome/browser/extensions/convert_web_app_unittest.cc
@@ -27,10 +27,12 @@ #include "extensions/common/extension_icon_set.h" #include "extensions/common/extension_resource.h" #include "extensions/common/manifest_constants.h" +#include "extensions/common/manifest_handlers/file_handler_info.h" #include "extensions/common/manifest_handlers/icons_handler.h" #include "extensions/common/permissions/permission_set.h" #include "extensions/common/permissions/permissions_data.h" #include "extensions/common/url_pattern.h" +#include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/codec/png_codec.h" #include "url/gurl.h" @@ -409,4 +411,70 @@ EXPECT_EQ(web_app.scope, GetScopeURLFromBookmarkApp(extension.get())); } +// Tests that |file_handler| on the WebAppManifest is correctly converted +// to |file_handlers| on an extension manifest. +TEST(ExtensionFromWebApp, FileHandlersAreCorrectlyConverted) { + base::ScopedTempDir extensions_dir; + ASSERT_TRUE(extensions_dir.CreateUniqueTempDir()); + + WebApplicationInfo web_app; + web_app.title = base::ASCIIToUTF16("Graphr"); + web_app.description = base::ASCIIToUTF16("A magical graphy thing"); + web_app.app_url = GURL("https://not-a-real-site.not-a-tld/"); + web_app.scope = GURL("https://not-a-real-site.not-a-tld/"); + + { + blink::Manifest::FileHandler file_handler; + + blink::Manifest::FileFilter graph; + graph.name = base::ASCIIToUTF16("Graph"); + graph.accept.push_back(base::ASCIIToUTF16("text/svg+xml")); + graph.accept.push_back(base::ASCIIToUTF16("")); + graph.accept.push_back(base::ASCIIToUTF16(".svg")); + file_handler.push_back(graph); + + blink::Manifest::FileFilter raw; + raw.name = base::ASCIIToUTF16("Raw"); + raw.accept.push_back(base::ASCIIToUTF16(".csv")); + raw.accept.push_back(base::ASCIIToUTF16("text/csv")); + file_handler.push_back(raw); + + web_app.file_handler = + base::Optional<blink::Manifest::FileHandler>(std::move(file_handler)); + } + + scoped_refptr<Extension> extension = ConvertWebAppToExtension( + web_app, GetTestTime(1978, 12, 11, 0, 0, 0, 0), extensions_dir.GetPath(), + Extension::NO_FLAGS, Manifest::INTERNAL); + + ASSERT_TRUE(extension.get()); + + const std::vector<extensions::FileHandlerInfo> file_handler_info = + *extensions::FileHandlers::GetFileHandlers(extension.get()); + + EXPECT_EQ(2u, file_handler_info.size()); + + EXPECT_EQ("Graph", file_handler_info[0].id); + EXPECT_FALSE(file_handler_info[0].include_directories); + EXPECT_EQ(extensions::file_handler_verbs::kOpenWith, + file_handler_info[0].verb); + // Extensions should contain SVG, and only SVG + EXPECT_THAT(file_handler_info[0].extensions, + testing::UnorderedElementsAre("svg")); + // Mime types should contain text/svg+xml and only text/svg+xml + EXPECT_THAT(file_handler_info[0].types, + testing::UnorderedElementsAre("text/svg+xml")); + + EXPECT_EQ("Raw", file_handler_info[1].id); + EXPECT_FALSE(file_handler_info[1].include_directories); + EXPECT_EQ(extensions::file_handler_verbs::kOpenWith, + file_handler_info[1].verb); + // Extensions should contain csv, and only csv + EXPECT_THAT(file_handler_info[1].extensions, + testing::UnorderedElementsAre("csv")); + // Mime types should contain text/csv and only text/csv + EXPECT_THAT(file_handler_info[1].types, + testing::UnorderedElementsAre("text/csv")); +} + } // namespace extensions
diff --git a/chrome/browser/extensions/updater/extension_update_client_base_browsertest.cc b/chrome/browser/extensions/updater/extension_update_client_base_browsertest.cc index cdd9153e..6f4bf35 100644 --- a/chrome/browser/extensions/updater/extension_update_client_base_browsertest.cc +++ b/chrome/browser/extensions/updater/extension_update_client_base_browsertest.cc
@@ -30,11 +30,9 @@ : public extensions::ChromeUpdateClientConfig { public: TestChromeUpdateClientConfig(content::BrowserContext* context, - bool use_JSON, const std::vector<GURL>& update_url, const std::vector<GURL>& ping_url) : extensions::ChromeUpdateClientConfig(context), - use_JSON_(use_JSON), update_url_(update_url), ping_url_(ping_url) {} @@ -47,16 +45,13 @@ std::unique_ptr<update_client::ProtocolHandlerFactory> GetProtocolHandlerFactory() const final { - if (use_JSON_) - return std::make_unique<update_client::ProtocolHandlerFactoryJSON>(); - return std::make_unique<update_client::ProtocolHandlerFactoryXml>(); + return std::make_unique<update_client::ProtocolHandlerFactoryJSON>(); } protected: ~TestChromeUpdateClientConfig() override = default; private: - bool use_JSON_ = false; std::vector<GURL> update_url_; std::vector<GURL> ping_url_; @@ -116,10 +111,9 @@ } // namespace -ExtensionUpdateClientBaseTest::ExtensionUpdateClientBaseTest(bool use_JSON) +ExtensionUpdateClientBaseTest::ExtensionUpdateClientBaseTest() : https_server_for_update_(net::EmbeddedTestServer::TYPE_HTTPS), - https_server_for_ping_(net::EmbeddedTestServer::TYPE_HTTPS), - use_JSON_(use_JSON) {} + https_server_for_ping_(net::EmbeddedTestServer::TYPE_HTTPS) {} ExtensionUpdateClientBaseTest::~ExtensionUpdateClientBaseTest() {} @@ -135,12 +129,12 @@ ExtensionUpdateClientBaseTest::ChromeUpdateClientConfigFactory() const { return base::BindRepeating( [](const std::vector<GURL>& update_url, const std::vector<GURL>& ping_url, - bool use_JSON, content::BrowserContext* context) + content::BrowserContext* context) -> scoped_refptr<ChromeUpdateClientConfig> { return base::MakeRefCounted<TestChromeUpdateClientConfig>( - context, use_JSON, update_url, ping_url); + context, update_url, ping_url); }, - GetUpdateUrls(), GetPingUrls(), use_JSON_); + GetUpdateUrls(), GetPingUrls()); } void ExtensionUpdateClientBaseTest::SetUp() {
diff --git a/chrome/browser/extensions/updater/extension_update_client_base_browsertest.h b/chrome/browser/extensions/updater/extension_update_client_base_browsertest.h index dd17e73..68d6e87 100644 --- a/chrome/browser/extensions/updater/extension_update_client_base_browsertest.h +++ b/chrome/browser/extensions/updater/extension_update_client_base_browsertest.h
@@ -40,7 +40,7 @@ public: using ConfigFactoryCallback = ChromeUpdateClientConfig::FactoryCallback; - explicit ExtensionUpdateClientBaseTest(bool use_JSON); + ExtensionUpdateClientBaseTest(); ~ExtensionUpdateClientBaseTest() override; // ExtensionBrowserTest: @@ -87,8 +87,6 @@ net::EmbeddedTestServer https_server_for_update_; net::EmbeddedTestServer https_server_for_ping_; - bool use_JSON_ = false; - private: bool OnRequest(content::URLLoaderInterceptor::RequestParams* params);
diff --git a/chrome/browser/extensions/updater/update_service_browsertest.cc b/chrome/browser/extensions/updater/update_service_browsertest.cc index 0edfb421..84970c1 100644 --- a/chrome/browser/extensions/updater/update_service_browsertest.cc +++ b/chrome/browser/extensions/updater/update_service_browsertest.cc
@@ -40,10 +40,9 @@ } // namespace -class UpdateServiceTest : public ExtensionUpdateClientBaseTest, - public testing::WithParamInterface<bool> { +class UpdateServiceTest : public ExtensionUpdateClientBaseTest { public: - UpdateServiceTest() : ExtensionUpdateClientBaseTest(GetParam()) {} + UpdateServiceTest() : ExtensionUpdateClientBaseTest() {} ~UpdateServiceTest() override {} void SetUpCommandLine(base::CommandLine* command_line) override { @@ -56,27 +55,15 @@ bool ShouldEnableContentVerification() override { return true; } }; -// This test is parameterized for using JSON or XML serialization. |true| means -// JSON serialization is used. -INSTANTIATE_TEST_SUITE_P(Parameterized, UpdateServiceTest, testing::Bool()); - -IN_PROC_BROWSER_TEST_P(UpdateServiceTest, NoUpdate) { +IN_PROC_BROWSER_TEST_F(UpdateServiceTest, NoUpdate) { // Verify that UpdateService runs correctly when there's no update. base::ScopedAllowBlockingForTesting allow_io; base::HistogramTester histogram_tester; // Mock a no-update response. - if (use_JSON_) { - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), - test_data_dir_.AppendASCII( - "updater/updatecheck_reply_noupdate_1.json"))); - } else { - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - test_data_dir_.AppendASCII( - "updater/updatecheck_reply_noupdate_1.xml"))); - } + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), + test_data_dir_.AppendASCII("updater/updatecheck_reply_noupdate_1.json"))); const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx"); const Extension* extension = @@ -117,37 +104,24 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); - if (use_JSON_) { const auto root = base::JSONReader::Read(update_request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.10", app.FindKey("version")->GetString()); EXPECT_TRUE(app.FindKey("enabled")->GetBool()); - } else { - EXPECT_THAT(update_request, - ::testing::HasSubstr(base::StringPrintf( - R"(<app appid="%s" version="0.10")", kExtensionId))); - EXPECT_THAT(update_request, ::testing::HasSubstr(R"(enabled="1")")); - } } -IN_PROC_BROWSER_TEST_P(UpdateServiceTest, UpdateCheckError) { +IN_PROC_BROWSER_TEST_F(UpdateServiceTest, UpdateCheckError) { // Verify that UpdateService works correctly when there's an error in the // update check phase. base::ScopedAllowBlockingForTesting allow_io; base::HistogramTester histogram_tester; // Mock an update check error. - if (use_JSON_) { ASSERT_TRUE(update_interceptor_->ExpectRequest( std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), net::HTTP_FORBIDDEN)); - } else { - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - net::HTTP_FORBIDDEN)); - } const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx"); const Extension* extension = @@ -190,43 +164,27 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); - if (use_JSON_) { const auto root = base::JSONReader::Read(update_request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.10", app.FindKey("version")->GetString()); EXPECT_TRUE(app.FindKey("enabled")->GetBool()); - } else { - EXPECT_THAT(update_request, - ::testing::HasSubstr(base::StringPrintf( - R"(<app appid="%s" version="0.10")", kExtensionId))); - EXPECT_THAT(update_request, ::testing::HasSubstr(R"(enabled="1")")); - } } -IN_PROC_BROWSER_TEST_P(UpdateServiceTest, TwoUpdateCheckErrors) { +IN_PROC_BROWSER_TEST_F(UpdateServiceTest, TwoUpdateCheckErrors) { // Verify that the UMA counters are emitted properly when there are 2 update // checks with different number of extensions, both of which result in errors. base::ScopedAllowBlockingForTesting allow_io; base::HistogramTester histogram_tester; // Mock update check errors. - if (use_JSON_) { ASSERT_TRUE(update_interceptor_->ExpectRequest( std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), net::HTTP_NOT_MODIFIED)); ASSERT_TRUE(update_interceptor_->ExpectRequest( std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), net::HTTP_USE_PROXY)); - } else { - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - net::HTTP_NOT_MODIFIED)); - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - net::HTTP_USE_PROXY)); - } const base::FilePath crx_path1 = test_data_dir_.AppendASCII("updater/v1.crx"); const base::FilePath crx_path2 = test_data_dir_.AppendASCII("updater/v2.crx"); @@ -276,12 +234,11 @@ << ping_interceptor_->GetRequestsAsString(); } -IN_PROC_BROWSER_TEST_P(UpdateServiceTest, SuccessfulUpdate) { +IN_PROC_BROWSER_TEST_F(UpdateServiceTest, SuccessfulUpdate) { base::ScopedAllowBlockingForTesting allow_io; base::HistogramTester histogram_tester; // Mock an update response. - if (use_JSON_) { const base::FilePath update_response = test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.json"); const base::FilePath ping_response = @@ -292,18 +249,6 @@ ASSERT_TRUE(ping_interceptor_->ExpectRequest( std::make_unique<update_client::PartialMatch>(R"("eventtype":)"), ping_response)); - } else { - const base::FilePath update_response = - test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.xml"); - const base::FilePath ping_response = - test_data_dir_.AppendASCII("updater/ping_reply_1.xml"); - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - update_response)); - ASSERT_TRUE(ping_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("eventtype"), - ping_response)); - } const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx"); set_interceptor_hook(base::BindLambdaForTesting( @@ -354,28 +299,20 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); - if (use_JSON_) { const auto root = base::JSONReader::Read(update_request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString()); EXPECT_EQ("0.10", app.FindKey("version")->GetString()); EXPECT_TRUE(app.FindKey("enabled")->GetBool()); - } else { - EXPECT_THAT(update_request, - ::testing::HasSubstr(base::StringPrintf( - R"(<app appid="%s" version="0.10")", kExtensionId))); - EXPECT_THAT(update_request, ::testing::HasSubstr(R"(enabled="1")")); - } } -IN_PROC_BROWSER_TEST_P(UpdateServiceTest, PolicyCorrupted) { +IN_PROC_BROWSER_TEST_F(UpdateServiceTest, PolicyCorrupted) { base::ScopedAllowBlockingForTesting allow_io; ExtensionSystem* system = ExtensionSystem::Get(profile()); ExtensionService* service = extension_service(); - if (use_JSON_) { const base::FilePath update_response = test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.json"); const base::FilePath ping_response = @@ -386,18 +323,6 @@ ASSERT_TRUE(ping_interceptor_->ExpectRequest( std::make_unique<update_client::PartialMatch>(R"("eventtype":)"), ping_response)); - } else { - const base::FilePath update_response = - test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.xml"); - const base::FilePath ping_response = - test_data_dir_.AppendASCII("updater/ping_reply_1.xml"); - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - update_response)); - ASSERT_TRUE(ping_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("eventtype"), - ping_response)); - } const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx"); set_interceptor_hook(base::BindLambdaForTesting( @@ -460,7 +385,6 @@ // - <disabled reason="1024"/> const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); - if (use_JSON_) { const auto root = base::JSONReader::Read(update_request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -472,21 +396,9 @@ const auto& disabled = app.FindKey("disabled")->GetList()[0]; EXPECT_EQ(disable_reason::DISABLE_CORRUPTED, disabled.FindKey("reason")->GetInt()); - } else { - EXPECT_THAT(update_request, - ::testing::HasSubstr(base::StringPrintf( - R"(<app appid="%s" version="0.0.0.0")", kExtensionId))); - EXPECT_THAT( - update_request, - ::testing::HasSubstr( - R"(installsource="reinstall" installedby="policy" enabled="0")")); - EXPECT_THAT(update_request, ::testing::HasSubstr(base::StringPrintf( - R"(<disabled reason="%d"/>)", - disable_reason::DISABLE_CORRUPTED))); - } } -IN_PROC_BROWSER_TEST_P(UpdateServiceTest, UninstallExtensionWhileUpdating) { +IN_PROC_BROWSER_TEST_F(UpdateServiceTest, UninstallExtensionWhileUpdating) { // This test is to verify that the extension updater engine (update client) // works correctly when an extension is uninstalled when the extension updater // is in progress. @@ -525,7 +437,7 @@ class PolicyUpdateServiceTest : public ExtensionUpdateClientBaseTest, public testing::WithParamInterface<bool> { public: - PolicyUpdateServiceTest() : ExtensionUpdateClientBaseTest(GetParam()) {} + PolicyUpdateServiceTest() : ExtensionUpdateClientBaseTest() {} ~PolicyUpdateServiceTest() override {} void SetUpCommandLine(base::CommandLine* command_line) override { @@ -574,7 +486,6 @@ params->client.get()); return true; })); - if (use_JSON_) { const base::FilePath update_response = test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.json"); const base::FilePath ping_response = @@ -604,37 +515,6 @@ ASSERT_TRUE(ping_interceptor_->ExpectRequest( std::make_unique<update_client::PartialMatch>(R"("eventtype":)"), ping_response)); - } else { - const base::FilePath update_response = - test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.xml"); - const base::FilePath ping_response = - test_data_dir_.AppendASCII("updater/ping_reply_1.xml"); - - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - update_response)); - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - update_response)); - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - update_response)); - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - update_response)); - ASSERT_TRUE(ping_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("eventtype"), - ping_response)); - ASSERT_TRUE(ping_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("eventtype"), - ping_response)); - ASSERT_TRUE(ping_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("eventtype"), - ping_response)); - ASSERT_TRUE(ping_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("eventtype"), - ping_response)); - } } std::vector<GURL> GetUpdateUrls() const override { @@ -655,16 +535,10 @@ content_verifier_test::DownloaderTestDelegate downloader_; }; -// This test is parameterized for using JSON or XML serialization. |true| means -// JSON serialization is used. -INSTANTIATE_TEST_SUITE_P(Parameterized, - PolicyUpdateServiceTest, - testing::Bool()); - // Tests that if CheckForExternalUpdates() fails, then we retry reinstalling // corrupted policy extensions. For example: if network is unavailable, // CheckForExternalUpdates() will fail. -IN_PROC_BROWSER_TEST_P(PolicyUpdateServiceTest, FailedUpdateRetries) { +IN_PROC_BROWSER_TEST_F(PolicyUpdateServiceTest, FailedUpdateRetries) { ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); ExtensionService* service = extension_service(); ContentVerifier* verifier = @@ -711,7 +585,6 @@ // - <disabled reason="1024"/> const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); - if (use_JSON_) { const auto root = base::JSONReader::Read(update_request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -723,21 +596,9 @@ const auto& disabled = app.FindKey("disabled")->GetList()[0]; EXPECT_EQ(disable_reason::DISABLE_CORRUPTED, disabled.FindKey("reason")->GetInt()); - } else { - EXPECT_THAT(update_request, - ::testing::HasSubstr(base::StringPrintf( - R"(<app appid="%s" version="0.0.0.0")", id_.c_str()))); - EXPECT_THAT( - update_request, - ::testing::HasSubstr( - R"(installsource="reinstall" installedby="policy" enabled="0")")); - EXPECT_THAT(update_request, ::testing::HasSubstr(base::StringPrintf( - R"(<disabled reason="%d"/>)", - disable_reason::DISABLE_CORRUPTED))); - } } -IN_PROC_BROWSER_TEST_P(PolicyUpdateServiceTest, Backoff) { +IN_PROC_BROWSER_TEST_F(PolicyUpdateServiceTest, Backoff) { ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); ContentVerifier* verifier = ExtensionSystem::Get(profile())->content_verifier(); @@ -789,7 +650,7 @@ // We want to test what happens at startup with a corroption-disabled policy // force installed extension. So we set that up in the PRE test here. -IN_PROC_BROWSER_TEST_P(PolicyUpdateServiceTest, PRE_PolicyCorruptedOnStartup) { +IN_PROC_BROWSER_TEST_F(PolicyUpdateServiceTest, PRE_PolicyCorruptedOnStartup) { // This is to not allow any corrupted resintall to proceed. content_verifier_test::DelayTracker delay_tracker; ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); @@ -818,7 +679,7 @@ } // Now actually test what happens on the next startup after the PRE test above. -IN_PROC_BROWSER_TEST_P(PolicyUpdateServiceTest, PolicyCorruptedOnStartup) { +IN_PROC_BROWSER_TEST_F(PolicyUpdateServiceTest, PolicyCorruptedOnStartup) { // Depdending on timing, the extension may have already been reinstalled // between SetUpInProcessBrowserTestFixture and now (usually not during local // testing on a developer machine, but sometimes on a heavily loaded system @@ -843,7 +704,6 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); - if (use_JSON_) { const auto root = base::JSONReader::Read(update_request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -855,18 +715,6 @@ const auto& disabled = app.FindKey("disabled")->GetList()[0]; EXPECT_EQ(disable_reason::DISABLE_CORRUPTED, disabled.FindKey("reason")->GetInt()); - } else { - EXPECT_THAT(update_request, - ::testing::HasSubstr(base::StringPrintf( - R"(<app appid="%s" version="0.0.0.0")", id_.c_str()))); - EXPECT_THAT( - update_request, - ::testing::HasSubstr( - R"(installsource="reinstall" installedby="policy" enabled="0")")); - EXPECT_THAT(update_request, ::testing::HasSubstr(base::StringPrintf( - R"(<disabled reason="%d"/>)", - disable_reason::DISABLE_CORRUPTED))); - } } } // namespace extensions
diff --git a/chrome/browser/loader/chrome_navigation_data.cc b/chrome/browser/loader/chrome_navigation_data.cc index 227fac7..575f2d483 100644 --- a/chrome/browser/loader/chrome_navigation_data.cc +++ b/chrome/browser/loader/chrome_navigation_data.cc
@@ -5,33 +5,56 @@ #include "chrome/browser/loader/chrome_navigation_data.h" #include "base/memory/ptr_util.h" +#include "base/supports_user_data.h" #include "net/url_request/url_request.h" const void* const kChromeNavigationDataUserDataKey = &kChromeNavigationDataUserDataKey; +namespace { + +// UserData object that owns ChromeNavigationData. This is used rather than +// having ChromeNavigationData directly extend base::SupportsUserData::Data to +// avoid naming conflicts between Data::Clone() and +// content::NavigationData::Clone(). +class NavigationDataOwner : public base::SupportsUserData::Data { + public: + NavigationDataOwner() = default; + ~NavigationDataOwner() override = default; + + ChromeNavigationData* data() { return &data_; } + + private: + ChromeNavigationData data_; + + DISALLOW_COPY_AND_ASSIGN(NavigationDataOwner); +}; + +} // namespace + ChromeNavigationData::ChromeNavigationData() {} ChromeNavigationData::~ChromeNavigationData() {} +// static ChromeNavigationData* ChromeNavigationData::GetDataAndCreateIfNecessary( net::URLRequest* request) { if (!request) return nullptr; - ChromeNavigationData* data = static_cast<ChromeNavigationData*>( + NavigationDataOwner* data_owner_ptr = static_cast<NavigationDataOwner*>( request->GetUserData(kChromeNavigationDataUserDataKey)); - if (data) - return data; - data = new ChromeNavigationData(); - request->SetUserData(kChromeNavigationDataUserDataKey, - base::WrapUnique(data)); - return data; + if (data_owner_ptr) + return data_owner_ptr->data(); + std::unique_ptr<NavigationDataOwner> data_owner = + std::make_unique<NavigationDataOwner>(); + data_owner_ptr = data_owner.get(); + request->SetUserData(kChromeNavigationDataUserDataKey, std::move(data_owner)); + return data_owner_ptr->data(); } std::unique_ptr<content::NavigationData> ChromeNavigationData::Clone() const { std::unique_ptr<ChromeNavigationData> copy(new ChromeNavigationData()); - if (data_reduction_proxy_data_) { + if (data_reduction_proxy_data_) copy->SetDataReductionProxyData(data_reduction_proxy_data_->DeepCopy()); - } return std::move(copy); }
diff --git a/chrome/browser/loader/chrome_navigation_data.h b/chrome/browser/loader/chrome_navigation_data.h index 854be05..cb7672f 100644 --- a/chrome/browser/loader/chrome_navigation_data.h +++ b/chrome/browser/loader/chrome_navigation_data.h
@@ -8,7 +8,6 @@ #include <memory> #include "base/macros.h" -#include "base/supports_user_data.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h" #include "content/public/browser/navigation_data.h" @@ -16,8 +15,7 @@ class URLRequest; } -class ChromeNavigationData : public content::NavigationData, - public base::SupportsUserData::Data { +class ChromeNavigationData : public content::NavigationData { public: ChromeNavigationData(); ~ChromeNavigationData() override;
diff --git a/chrome/browser/notifications/notification_schedule_service_factory.cc b/chrome/browser/notifications/notification_schedule_service_factory.cc index baa6860..a259c32 100644 --- a/chrome/browser/notifications/notification_schedule_service_factory.cc +++ b/chrome/browser/notifications/notification_schedule_service_factory.cc
@@ -4,7 +4,10 @@ #include "chrome/browser/notifications/notification_schedule_service_factory.h" -#include "chrome/browser/notifications/scheduler/notification_schedule_service_impl.h" +#include "chrome/browser/notifications/notification_background_task_scheduler_impl.h" +#include "chrome/browser/notifications/scheduler/notification_schedule_service.h" +#include "chrome/browser/notifications/scheduler/notification_scheduler_context.h" +#include "chrome/browser/notifications/scheduler/schedule_service_factory_helper.h" #include "chrome/browser/profiles/incognito_helpers.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" @@ -33,9 +36,12 @@ KeyedService* NotificationScheduleServiceFactory::BuildServiceInstanceFor( content::BrowserContext* context) const { - // TODO(xingliu): Build the actual instance here. - return static_cast<KeyedService*>( - new notifications::NotificationScheduleServiceImpl()); + // Pass all dependencies to notification scheduler and build the service + // instance. + auto background_task_scheduler = + std::make_unique<NotificationBackgroundTaskSchedulerImpl>(); + return notifications::CreateNotificationScheduleService( + std::move(background_task_scheduler)); } content::BrowserContext*
diff --git a/chrome/browser/notifications/scheduler/BUILD.gn b/chrome/browser/notifications/scheduler/BUILD.gn index 53c9dd0..a3af336 100644 --- a/chrome/browser/notifications/scheduler/BUILD.gn +++ b/chrome/browser/notifications/scheduler/BUILD.gn
@@ -9,10 +9,8 @@ } group("scheduler") { - # TODO(xingliu): Change this to a source set when we have code to be used by - # NotificationScheduleServiceFactory. deps = [ - ":lib", + ":factory", ] public_deps = [ @@ -39,9 +37,25 @@ ] } +# The embedder can depend on this target to get the internal library. +source_set("factory") { + sources = [ + "schedule_service_factory_helper.cc", + "schedule_service_factory_helper.h", + ] + + deps = [ + ":lib", + ":public", + "//base", + "//components/keyed_service/core", + ] +} + # Internal library that embedders should not directly depend on. source_set("lib") { visibility = [ + ":factory", ":scheduler", ":unit_tests", "//chrome/browser/notifications/scheduler/test:test_lib", @@ -66,6 +80,8 @@ "notification_entry.h", "notification_schedule_service_impl.cc", "notification_schedule_service_impl.h", + "notification_scheduler.cc", + "notification_scheduler.h", "notification_scheduler_context.cc", "notification_scheduler_context.h", "proto_conversion.cc",
diff --git a/chrome/browser/notifications/scheduler/display_decider.cc b/chrome/browser/notifications/scheduler/display_decider.cc index 574a3643..6a948a4 100644 --- a/chrome/browser/notifications/scheduler/display_decider.cc +++ b/chrome/browser/notifications/scheduler/display_decider.cc
@@ -75,9 +75,7 @@ // TODO(xingliu): Ensure deprecated clients will not have data in storage. DCHECK(std::find(clients_.begin(), clients_.end(), client_state->type) != clients_.end()); - for (const auto& impression_it : client_state->impressions) { - const auto& impression = impression_it.second; - + for (const auto& impression : client_state->impressions) { // Tracks last notification shown to the user. if (impression.create_time > last_shown_time) { last_shown_time = impression.create_time;
diff --git a/chrome/browser/notifications/scheduler/icon_store.cc b/chrome/browser/notifications/scheduler/icon_store.cc index 004964a..60245c0 100644 --- a/chrome/browser/notifications/scheduler/icon_store.cc +++ b/chrome/browser/notifications/scheduler/icon_store.cc
@@ -11,12 +11,12 @@ namespace leveldb_proto { -void DataToProto(const notifications::IconEntry& icon_entry, +void DataToProto(notifications::IconEntry* icon_entry, notifications::proto::Icon* proto) { IconEntryToProto(icon_entry, proto); } -void ProtoToData(const notifications::proto::Icon& proto, +void ProtoToData(notifications::proto::Icon* proto, notifications::IconEntry* icon_entry) { IconProtoToEntry(proto, icon_entry); }
diff --git a/chrome/browser/notifications/scheduler/icon_store.h b/chrome/browser/notifications/scheduler/icon_store.h index 70f117c..a05645b 100644 --- a/chrome/browser/notifications/scheduler/icon_store.h +++ b/chrome/browser/notifications/scheduler/icon_store.h
@@ -17,10 +17,10 @@ // Forward declaration for proto conversion. namespace leveldb_proto { -void DataToProto(const notifications::IconEntry& icon_entry, +void DataToProto(notifications::IconEntry* icon_entry, notifications::proto::Icon* proto); -void ProtoToData(const notifications::proto::Icon& proto, +void ProtoToData(notifications::proto::Icon* proto, notifications::IconEntry* icon_entry); } // namespace leveldb_proto
diff --git a/chrome/browser/notifications/scheduler/icon_store_unittest.cc b/chrome/browser/notifications/scheduler/icon_store_unittest.cc index 77f63b5..c15c4c8 100644 --- a/chrome/browser/notifications/scheduler/icon_store_unittest.cc +++ b/chrome/browser/notifications/scheduler/icon_store_unittest.cc
@@ -36,7 +36,7 @@ entry.uuid = kEntryId; entry.data = kEntryData; proto::Icon proto; - leveldb_proto::DataToProto(entry, &proto); + leveldb_proto::DataToProto(&entry, &proto); db_entries_.emplace(kEntryKey, proto); auto db =
diff --git a/chrome/browser/notifications/scheduler/impression_history_tracker.cc b/chrome/browser/notifications/scheduler/impression_history_tracker.cc index 6052a5a..c482f21 100644 --- a/chrome/browser/notifications/scheduler/impression_history_tracker.cc +++ b/chrome/browser/notifications/scheduler/impression_history_tracker.cc
@@ -36,7 +36,7 @@ for (auto it = client_state->impressions.begin(); it != client_state->impressions.end();) { - auto* impression = &it->second; + auto* impression = &*it; // Prune out expired impression. if (now - impression->create_time > config_.impression_expiration) {
diff --git a/chrome/browser/notifications/scheduler/impression_history_tracker_unittest.cc b/chrome/browser/notifications/scheduler/impression_history_tracker_unittest.cc index 2f4b8c1..a199a4a0 100644 --- a/chrome/browser/notifications/scheduler/impression_history_tracker_unittest.cc +++ b/chrome/browser/notifications/scheduler/impression_history_tracker_unittest.cc
@@ -35,8 +35,10 @@ DCHECK(output_it != output.end()); EXPECT_EQ(*expected.second, *output_it->second) << "Unmatch client states: \n" - << "Expected:" << expected.second->DebugPrint() << " \n" - << "Acutual: " << output_it->second->DebugPrint(); + << "Expected: \n" + << expected.second->DebugPrint() << " \n" + << "Acutual: \n" + << output_it->second->DebugPrint(); } } @@ -87,16 +89,24 @@ TestCase test_case; auto expired_create_time = base::Time::Now() - base::TimeDelta::FromDays(1) - 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 */}; + test_case.input = {{SchedulerClientType::kTest1, 2 /* current_max_daily_show */, - {{expired_create_time, UserFeedback::kUnknown, - ImpressionResult::kUnknown, false /* integrated */}}, + {expired, expired, not_expired}, base::nullopt /* suppression_info */}}; // Expired impression created in |expired_create_time| should be deleted. + // No change expected on the next impression, which is not expired and no user + // feedback . test_case.expected = {{SchedulerClientType::kTest1, 2 /* current_max_daily_show */, - {}, + {not_expired}, base::nullopt /* suppression_info */}}; RunTestCase(std::move(test_case));
diff --git a/chrome/browser/notifications/scheduler/impression_types.cc b/chrome/browser/notifications/scheduler/impression_types.cc index 92ca5f5..efdf022 100644 --- a/chrome/browser/notifications/scheduler/impression_types.cc +++ b/chrome/browser/notifications/scheduler/impression_types.cc
@@ -46,8 +46,7 @@ "impressions.size(): %zu \n", static_cast<int>(type), current_max_daily_show, impressions.size()); - for (const auto& it : impressions) { - const auto& impression = it.second; + for (const auto& impression : impressions) { std::ostringstream stream; stream << "Impression, create_time:" << impression.create_time << " \n" << "feedback: " << static_cast<int>(impression.feedback) << " \n"
diff --git a/chrome/browser/notifications/scheduler/impression_types.h b/chrome/browser/notifications/scheduler/impression_types.h index 4627197..53f2c31d 100644 --- a/chrome/browser/notifications/scheduler/impression_types.h +++ b/chrome/browser/notifications/scheduler/impression_types.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_IMPRESSION_TYPES_H_ #define CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_IMPRESSION_TYPES_H_ +#include <deque> #include <map> #include "base/optional.h" @@ -69,7 +70,7 @@ // to the user and the history of user interactions to a particular notification // client. struct ClientState { - using Impressions = std::map<base::Time, Impression>; + using Impressions = std::deque<Impression>; explicit ClientState(SchedulerClientType type); explicit ClientState(const ClientState& other); ~ClientState();
diff --git a/chrome/browser/notifications/scheduler/notification_schedule_service_impl.cc b/chrome/browser/notifications/scheduler/notification_schedule_service_impl.cc index 4ba86c4e..fa5dd88 100644 --- a/chrome/browser/notifications/scheduler/notification_schedule_service_impl.cc +++ b/chrome/browser/notifications/scheduler/notification_schedule_service_impl.cc
@@ -4,20 +4,22 @@ #include "chrome/browser/notifications/scheduler/notification_schedule_service_impl.h" -#include <memory> - #include "base/logging.h" #include "chrome/browser/notifications/scheduler/notification_params.h" +#include "chrome/browser/notifications/scheduler/notification_scheduler.h" +#include "chrome/browser/notifications/scheduler/notification_scheduler_context.h" namespace notifications { -NotificationScheduleServiceImpl::NotificationScheduleServiceImpl() = default; +NotificationScheduleServiceImpl::NotificationScheduleServiceImpl( + std::unique_ptr<NotificationSchedulerContext> context) + : scheduler_(NotificationScheduler::Create(std::move(context))) {} NotificationScheduleServiceImpl::~NotificationScheduleServiceImpl() = default; void NotificationScheduleServiceImpl::Schedule( std::unique_ptr<NotificationParams> notification_params) { - NOTIMPLEMENTED(); + scheduler_->Schedule(std::move(notification_params)); } } // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/notification_schedule_service_impl.h b/chrome/browser/notifications/scheduler/notification_schedule_service_impl.h index 5b394c3..46b14e0 100644 --- a/chrome/browser/notifications/scheduler/notification_schedule_service_impl.h +++ b/chrome/browser/notifications/scheduler/notification_schedule_service_impl.h
@@ -12,11 +12,14 @@ namespace notifications { +class NotificationScheduler; +class NotificationSchedulerContext; struct NotificationParams; class NotificationScheduleServiceImpl : public NotificationScheduleService { public: - NotificationScheduleServiceImpl(); + NotificationScheduleServiceImpl( + std::unique_ptr<NotificationSchedulerContext> context); ~NotificationScheduleServiceImpl() override; private: @@ -24,6 +27,9 @@ void Schedule( std::unique_ptr<NotificationParams> notification_params) override; + // Provides the actual notification scheduling functionalities. + std::unique_ptr<NotificationScheduler> scheduler_; + DISALLOW_COPY_AND_ASSIGN(NotificationScheduleServiceImpl); };
diff --git a/chrome/browser/notifications/scheduler/notification_scheduler.cc b/chrome/browser/notifications/scheduler/notification_scheduler.cc new file mode 100644 index 0000000..af50f3b --- /dev/null +++ b/chrome/browser/notifications/scheduler/notification_scheduler.cc
@@ -0,0 +1,47 @@ +// 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 "chrome/browser/notifications/scheduler/notification_scheduler.h" + +#include "base/logging.h" +#include "chrome/browser/notifications/scheduler/notification_params.h" +#include "chrome/browser/notifications/scheduler/notification_scheduler_context.h" + +namespace notifications { +namespace { + +// Implementation of NotificationScheduler. +class NotificationSchedulerImpl : public NotificationScheduler { + public: + NotificationSchedulerImpl( + std::unique_ptr<NotificationSchedulerContext> context) + : context_(std::move(context)) {} + + ~NotificationSchedulerImpl() override = default; + + private: + // NotificationScheduler implementation. + void Schedule( + std::unique_ptr<NotificationParams> notification_params) override { + NOTIMPLEMENTED(); + } + + std::unique_ptr<NotificationSchedulerContext> context_; + + DISALLOW_COPY_AND_ASSIGN(NotificationSchedulerImpl); +}; + +} // namespace + +// static +std::unique_ptr<NotificationScheduler> NotificationScheduler::Create( + std::unique_ptr<NotificationSchedulerContext> context) { + return std::make_unique<NotificationSchedulerImpl>(std::move(context)); +} + +NotificationScheduler::NotificationScheduler() = default; + +NotificationScheduler::~NotificationScheduler() = default; + +} // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/notification_scheduler.h b/chrome/browser/notifications/scheduler/notification_scheduler.h new file mode 100644 index 0000000..5605ce3 --- /dev/null +++ b/chrome/browser/notifications/scheduler/notification_scheduler.h
@@ -0,0 +1,38 @@ +// 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 CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_NOTIFICATION_SCHEDULER_H_ +#define CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_NOTIFICATION_SCHEDULER_H_ + +#include <memory> + +#include "base/macros.h" + +namespace notifications { + +class NotificationSchedulerContext; +struct NotificationParams; + +// Provides notification scheduling and throttling functionalities. This class +// glues all the subsystems together for notification scheduling system. +class NotificationScheduler { + public: + static std::unique_ptr<NotificationScheduler> Create( + std::unique_ptr<NotificationSchedulerContext> context); + + NotificationScheduler(); + virtual ~NotificationScheduler(); + + // Schedules a notification to show in the future. Throttling logic may apply + // based on |notification_params|. + virtual void Schedule( + std::unique_ptr<NotificationParams> notification_params) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(NotificationScheduler); +}; + +} // namespace notifications + +#endif // CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_NOTIFICATION_SCHEDULER_H_
diff --git a/chrome/browser/notifications/scheduler/notification_scheduler_context.cc b/chrome/browser/notifications/scheduler/notification_scheduler_context.cc index cc939b9..cde8211 100644 --- a/chrome/browser/notifications/scheduler/notification_scheduler_context.cc +++ b/chrome/browser/notifications/scheduler/notification_scheduler_context.cc
@@ -5,18 +5,16 @@ #include "chrome/browser/notifications/scheduler/notification_scheduler_context.h" #include "chrome/browser/notifications/scheduler/notification_background_task_scheduler.h" +#include "chrome/browser/notifications/scheduler/scheduler_config.h" namespace notifications { NotificationSchedulerContext::NotificationSchedulerContext( - std::unique_ptr<NotificationBackgroundTaskScheduler> scheduler) - : background_task_scheduler_(std::move(scheduler)) {} + std::unique_ptr<NotificationBackgroundTaskScheduler> scheduler, + std::unique_ptr<SchedulerConfig> config) + : background_task_scheduler_(std::move(scheduler)), + config_(std::move(config)) {} NotificationSchedulerContext::~NotificationSchedulerContext() = default; -NotificationBackgroundTaskScheduler* -NotificationSchedulerContext::GetBackgroundTaskScheduler() { - return background_task_scheduler_.get(); -} - } // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/notification_scheduler_context.h b/chrome/browser/notifications/scheduler/notification_scheduler_context.h index bf4ddbf..a5738db3 100644 --- a/chrome/browser/notifications/scheduler/notification_scheduler_context.h +++ b/chrome/browser/notifications/scheduler/notification_scheduler_context.h
@@ -12,6 +12,7 @@ namespace notifications { class NotificationBackgroundTaskScheduler; +struct SchedulerConfig; // Context that contains necessary components needed by the notification // scheduler to perform tasks. @@ -20,14 +21,22 @@ class NotificationSchedulerContext { public: NotificationSchedulerContext( - std::unique_ptr<NotificationBackgroundTaskScheduler> scheduler); + std::unique_ptr<NotificationBackgroundTaskScheduler> scheduler, + std::unique_ptr<SchedulerConfig> config); ~NotificationSchedulerContext(); - NotificationBackgroundTaskScheduler* GetBackgroundTaskScheduler(); + // Gets the background task scheduler. + NotificationBackgroundTaskScheduler* background_task_scheduler() { + return background_task_scheduler_.get(); + } + + // Gets system configuration. + const SchedulerConfig* config() const { return config_.get(); } private: std::unique_ptr<NotificationBackgroundTaskScheduler> background_task_scheduler_; + std::unique_ptr<SchedulerConfig> config_; DISALLOW_COPY_AND_ASSIGN(NotificationSchedulerContext); };
diff --git a/chrome/browser/notifications/scheduler/proto_conversion.cc b/chrome/browser/notifications/scheduler/proto_conversion.cc index 928f940..c42457c 100644 --- a/chrome/browser/notifications/scheduler/proto_conversion.cc +++ b/chrome/browser/notifications/scheduler/proto_conversion.cc
@@ -11,20 +11,16 @@ namespace notifications { -void IconEntryToProto(const IconEntry& entry, - notifications::proto::Icon* proto) { - proto->set_uuid(entry.uuid); - - // Copy large chunk of data to proto. - proto->set_icon(entry.data); +void IconEntryToProto(IconEntry* entry, notifications::proto::Icon* proto) { + proto->mutable_uuid()->swap(entry->uuid); + proto->mutable_icon()->swap(entry->data); } -void IconProtoToEntry(const proto::Icon& proto, - notifications::IconEntry* entry) { - DCHECK(proto.has_uuid()); - DCHECK(proto.has_icon()); - entry->data = proto.icon(); - entry->uuid = proto.uuid(); +void IconProtoToEntry(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()); } } // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/proto_conversion.h b/chrome/browser/notifications/scheduler/proto_conversion.h index c0ef3c6f..eee7422 100644 --- a/chrome/browser/notifications/scheduler/proto_conversion.h +++ b/chrome/browser/notifications/scheduler/proto_conversion.h
@@ -14,12 +14,10 @@ namespace notifications { // Converts an icon entry to icon proto. -void IconEntryToProto(const IconEntry& entry, - notifications::proto::Icon* proto); +void IconEntryToProto(IconEntry* entry, notifications::proto::Icon* proto); // Converts an icon proto to icon entry. -void IconProtoToEntry(const proto::Icon& proto, - notifications::IconEntry* entry); +void IconProtoToEntry(proto::Icon* proto, notifications::IconEntry* entry); } // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/proto_conversion_unittest.cc b/chrome/browser/notifications/scheduler/proto_conversion_unittest.cc index e4d5ae0d..ba37e9ad 100644 --- a/chrome/browser/notifications/scheduler/proto_conversion_unittest.cc +++ b/chrome/browser/notifications/scheduler/proto_conversion_unittest.cc
@@ -21,7 +21,7 @@ proto.set_icon(kData); IconEntry entry; - IconProtoToEntry(proto, &entry); + IconProtoToEntry(&proto, &entry); // Verify entry data. EXPECT_EQ(entry.uuid, kUuid); @@ -34,7 +34,7 @@ entry.uuid = kUuid; IconProto proto; - IconEntryToProto(entry, &proto); + IconEntryToProto(&entry, &proto); // Verify proto data. EXPECT_EQ(proto.icon(), kData);
diff --git a/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc new file mode 100644 index 0000000..899e3c0 --- /dev/null +++ b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc
@@ -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. + +#include "chrome/browser/notifications/scheduler/schedule_service_factory_helper.h" + +#include "chrome/browser/notifications/scheduler/notification_background_task_scheduler.h" +#include "chrome/browser/notifications/scheduler/notification_schedule_service_impl.h" +#include "chrome/browser/notifications/scheduler/notification_scheduler_context.h" +#include "chrome/browser/notifications/scheduler/scheduler_config.h" + +namespace notifications { + +KeyedService* CreateNotificationScheduleService( + std::unique_ptr<NotificationBackgroundTaskScheduler> + background_task_scheduler) { + auto config = SchedulerConfig::Create(); + auto context = std::make_unique<NotificationSchedulerContext>( + std::move(background_task_scheduler), std::move(config)); + return static_cast<KeyedService*>( + new NotificationScheduleServiceImpl(std::move(context))); +} + +} // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/schedule_service_factory_helper.h b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.h new file mode 100644 index 0000000..b30e421 --- /dev/null +++ b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.h
@@ -0,0 +1,27 @@ +// 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 CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_SCHEDULE_SERVICE_FACTORY_HELPER_H_ +#define CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_SCHEDULE_SERVICE_FACTORY_HELPER_H_ + +#include <memory> + +#include "base/macros.h" + +#include "components/keyed_service/core/keyed_service.h" + +namespace notifications { + +class NotificationBackgroundTaskScheduler; + +// Creates the notification schedule service with all the embedder level +// dependencies. This layer is mainly to forbid the embedder to depend on +// notification scheduler internal code. +KeyedService* CreateNotificationScheduleService( + std::unique_ptr<NotificationBackgroundTaskScheduler> + background_task_scheduler); + +} // namespace notifications + +#endif // CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_SCHEDULE_SERVICE_FACTORY_HELPER_H_
diff --git a/chrome/browser/notifications/scheduler/test/test_utils.cc b/chrome/browser/notifications/scheduler/test/test_utils.cc index b56b28d..38f17cd 100644 --- a/chrome/browser/notifications/scheduler/test/test_utils.cc +++ b/chrome/browser/notifications/scheduler/test/test_utils.cc
@@ -29,10 +29,10 @@ 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(impression.create_time, impression); + for (const auto& impression : test_data.impressions) { + client_state->impressions.emplace_back(impression); + } client_state->suppression_info = test_data.suppression_info; - client_states->emplace(test_data.type, std::move(client_state)); } }
diff --git a/chrome/browser/offline_pages/offline_page_mhtml_archiver.cc b/chrome/browser/offline_pages/offline_page_mhtml_archiver.cc index b64d6b5..4077f4fd 100644 --- a/chrome/browser/offline_pages/offline_page_mhtml_archiver.cc +++ b/chrome/browser/offline_pages/offline_page_mhtml_archiver.cc
@@ -125,8 +125,7 @@ params.remove_popup_overlay = create_archive_params.remove_popup_overlay; params.use_page_problem_detectors = create_archive_params.use_page_problem_detectors; - params.use_mojo_for_mhtml_serialization = - IsOnTheFlyMhtmlHashComputationEnabled(); + params.compute_contents_hash = IsOnTheFlyMhtmlHashComputationEnabled(); web_contents->GenerateMHTML( params,
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 5350a4d..796c1821 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -156,6 +156,7 @@ #include "extensions/browser/api/runtime/runtime_api.h" #include "extensions/browser/extension_prefs.h" #if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/crostini/crostini_share_path.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h" #include "chrome/browser/chromeos/settings/stats_reporting_controller.h" #include "chrome/browser/component_updater/metadata_table_chromeos.h" @@ -985,6 +986,8 @@ } #endif + // Added 4/2019 + crostini::CrostiniSharePath::MigratePersistedPathsToMultiVM(profile_prefs); #endif // Added 1/2019.
diff --git a/chrome/browser/prerender/prerender_link_manager.cc b/chrome/browser/prerender/prerender_link_manager.cc index 76421d7..2c50824 100644 --- a/chrome/browser/prerender/prerender_link_manager.cc +++ b/chrome/browser/prerender/prerender_link_manager.cc
@@ -25,6 +25,7 @@ #include "content/public/common/referrer.h" #include "extensions/buildflags/buildflags.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/common/prerender/prerender_rel_type.h" #include "ui/gfx/geometry/size.h" #include "url/gurl.h" @@ -41,12 +42,8 @@ namespace { -static_assert(PrerenderRelTypePrerender == 0x1, - "RelTypeHistogrameEnum must match PrerenderRelType"); -static_assert(PrerenderRelTypeNext == 0x2, - "RelTypeHistogramEnum must match PrerenderRelType"); constexpr int kRelTypeHistogramEnumMax = - (PrerenderRelTypePrerender | PrerenderRelTypeNext) + 1; + (blink::kPrerenderRelTypePrerender | blink::kPrerenderRelTypeNext) + 1; void RecordLinkManagerAdded(const uint32_t rel_types) { UMA_HISTOGRAM_ENUMERATION("Prerender.RelTypesLinkAdded", @@ -350,7 +347,7 @@ abandoned_prerenders.pop_front(); } - if (!(PrerenderRelTypePrerender & it->rel_types)) { + if (!(blink::kPrerenderRelTypePrerender & it->rel_types)) { prerenders_.erase(it); continue; }
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc index 1f9273e..87883ec 100644 --- a/chrome/browser/prerender/prerender_manager.cc +++ b/chrome/browser/prerender/prerender_manager.cc
@@ -67,6 +67,7 @@ #include "extensions/common/constants.h" #include "net/http/http_cache.h" #include "net/http/http_request_headers.h" +#include "third_party/blink/public/common/prerender/prerender_rel_type.h" #include "ui/gfx/geometry/rect.h" using chrome_browser_net::NetworkPredictionStatus; @@ -220,9 +221,9 @@ const uint32_t rel_types, const content::Referrer& referrer, const gfx::Size& size) { - Origin origin = rel_types & PrerenderRelTypePrerender ? - ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN : - ORIGIN_LINK_REL_NEXT; + Origin origin = rel_types & blink::kPrerenderRelTypePrerender + ? ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN + : ORIGIN_LINK_REL_NEXT; SessionStorageNamespace* session_storage_namespace = nullptr; // Unit tests pass in a process_id == -1. if (process_id != -1) {
diff --git a/chrome/browser/prerender/prerender_unittest.cc b/chrome/browser/prerender/prerender_unittest.cc index 9f44120..06cbcab 100644 --- a/chrome/browser/prerender/prerender_unittest.cc +++ b/chrome/browser/prerender/prerender_unittest.cc
@@ -49,6 +49,7 @@ #include "net/http/http_cache.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/prerender/prerender_rel_type.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "url/gurl.h" @@ -131,7 +132,7 @@ const gfx::Size kSize(640, 480); -const uint32_t kDefaultRelTypes = PrerenderRelTypePrerender; +const uint32_t kDefaultRelTypes = blink::kPrerenderRelTypePrerender; } // namespace
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index 3b08d0d..6abb20b 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -20,6 +20,7 @@ "discards:closure_compile", "downloads:closure_compile", "history:closure_compile", + "local_ntp:closure_compile", "local_state:closure_compile", "management:closure_compile", "md_user_manager:closure_compile",
diff --git a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.css b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.css index 0502cb7..7bf022a 100644 --- a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.css +++ b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.css
@@ -2,6 +2,26 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#arc-detailed-view-overlay { + background-color: rgb(255, 255, 192); + border: 1px solid #aaa; + display: none; + margin: 0; + max-height: 50%; + overflow-x: hidden; + overflow-y: auto; + position: absolute; +} + +#arc-detailed-view-overlay::-webkit-scrollbar { + height: 4px; + width: 4px; +} + +#arc-detailed-view-overlay::-webkit-scrollbar-thumb { + background-color: #888; +} + #arc-event-bands { margin: 0 auto; overflow: auto; @@ -11,7 +31,7 @@ #arc-event-band-tooltip { background-color: rgb(255, 255, 192); - border: 1px solid #a0a0a0; + border: 1px solid #aaa; display: none; pointer-events: none; position: absolute; @@ -19,25 +39,27 @@ width: 240px; } -#arc-event-band-tooltip.active { +#arc-event-band-tooltip.active, +#arc-detailed-view-overlay.active { display: block; } -.arc-events-inner-band { +.arc-cpu-view-title { + border-bottom: 1px solid #888; + font-size: 14px; + margin: 4px 0 4px 0; +} + +.arc-events-band { + display: block; + margin: 0; +} + +.arc-events-cpu-detailed-band { display: block; margin: 0 0 4px 0; } -.arc-events-inner-band-last-buffer { - display: block; - margin: 0 0 12px 0; -} - -.arc-events-top-band { - display: block; - margin: 0 0 8px 0; -} - .arc-events-band-title { align-items: center; border: none; @@ -71,7 +93,6 @@ content: '\002B'; } -.hidden.arc-events-inner-band, -.hidden.arc-events-top-band { +.hidden.arc-events-band { display: none; }
diff --git a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.html b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.html index fd8a787..b42be2a 100644 --- a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.html +++ b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.html
@@ -23,6 +23,7 @@ </div> <hr> <div id='arc-event-bands'></div> - <svg id='arc-event-band-tooltip'></svg> + <div id='arc-detailed-view-overlay'></div> + <div id='arc-event-band-tooltip'></div> </body> </html>
diff --git a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.js b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.js index 54bd0cd9..76b3125 100644 --- a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.js +++ b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing.js
@@ -18,6 +18,7 @@ }, false); chrome.send('ready'); chrome.send('setStopOnJank', [stopOnJank.checked]); + initializeUi(); }, setStatus: function(statusText) {
diff --git a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js index 3fb41fa..ab4af53f1 100644 --- a/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js +++ b/chrome/browser/resources/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.js
@@ -22,6 +22,11 @@ * event, |name| is used in tooltips. */ var eventAttributes = { + // kIdleIn + 0: {color: bandColor, name: 'idle'}, + // kIdleOut + 1: {color: '#ffbf00', name: 'active'}, + // kBufferQueueDequeueStart 100: {color: '#99cc00', name: 'app requests buffer'}, // kBufferQueueDequeueDone @@ -80,6 +85,10 @@ 504: {color: '#65f441', name: 'swap done'}, // kChromeOSJank 505: {color: '#ff0000', name: 'Chrome composition jank', width: 1.0}, + + // Service events. + // kTimeMark + 10000: {color: '#fff', name: 'Time mark', width: 0.75}, }; /** @@ -92,6 +101,8 @@ * sequence. */ var endSequenceEvents = { + // kIdleIn + 0: [], // kBufferQueueQueueDone 103: [], // kBufferQueueReleased @@ -108,28 +119,36 @@ // is the last. Different // pipelines may produce different sequences. Both event type may indicate // the end of the - /// sequence. + // sequence. 503: [500 /* kChromeOSDraw */], // kChromeOSSwapDone 504: [500 /* kChromeOSDraw */], }; /** - * Converts timestamp into pixel offset. 1 pixel corresponds 100 microseconds. - * - * @param {number} timestamp in microseconds. + * @type {DetailedInfoView}. + * Currently active detailed view. */ -function timestampToOffset(timestamp) { - return timestamp / 100.0; +var activeDetailedInfoView = null; + +/** + * Discards active detailed view if it exists. + */ +function discardDetailedInfo() { + if (activeDetailedInfoView) { + activeDetailedInfoView.discard(); + activeDetailedInfoView = null; + } } /** - * Opposite conversion of |timestampToOffset| - * - * @param {number} offset in pixels. + * Shows detailed view for |eventBand| in response to mouse click event + * |mouseEvent|. */ -function offsetToTime(offset) { - return offset * 100.0; +function showDetailedInfoForBand(eventBand, mouseEvent) { + discardDetailedInfo(); + activeDetailedInfoView = eventBand.showDetailedInfo(mouseEvent); + mouseEvent.preventDefault(); } /** @@ -142,10 +161,33 @@ return (timestamp / 1000.0).toFixed(1); } +/** + * Initialises UI by setting keyboard and mouse listeners to discard detailed + * view overlay. + */ +function initializeUi() { + document.body.onkeydown = function(event) { + // Escape and Enter. + if (event.key === 'Escape' || event.key === 'Enter') { + discardDetailedInfo(); + } + }; + + window.onclick = function(event) { + // Detect click outside the detailed view. + if (event.defaultPrevented || activeDetailedInfoView == null) { + return; + } + if (!activeDetailedInfoView.overlay.contains(event.target)) { + discardDetailedInfo(); + } + }; +} + /** Factory class for SVG elements. */ class SVG { // Creates rectangle element in the |svg| with provided attributes. - static addRect(svg, x, y, width, height, color) { + static addRect(svg, x, y, width, height, color, opacity) { var rect = document.createElementNS(svgNS, 'rect'); rect.setAttributeNS(null, 'x', x); rect.setAttributeNS(null, 'y', y); @@ -153,7 +195,11 @@ rect.setAttributeNS(null, 'height', height); rect.setAttributeNS(null, 'fill', color); rect.setAttributeNS(null, 'stroke', 'none'); + if (opacity) { + rect.setAttributeNS(null, 'fill-opacity', opacity); + } svg.appendChild(rect); + return rect; } // Creates line element in the |svg| with provided attributes. @@ -166,6 +212,7 @@ line.setAttributeNS(null, 'stroke', color); line.setAttributeNS(null, 'stroke-width', width); svg.appendChild(line); + return line; } // Creates circle element in the |svg| with provided attributes. @@ -178,6 +225,7 @@ circle.setAttributeNS(null, 'stroke', strokeColor); circle.setAttributeNS(null, 'stroke-width', strokeWidth); svg.appendChild(circle); + return circle; } // Creates text element in the |svg| with provided attributes. @@ -189,6 +237,7 @@ text.setAttributeNS(null, 'font-size', fontSize); text.appendChild(document.createTextNode(textContent)); svg.appendChild(text); + return text; } } @@ -197,9 +246,9 @@ * content. */ class EventBandTitle { - constructor(title, opt_iconContent) { + constructor(parent, title, className, opt_iconContent) { this.div = document.createElement('div'); - this.div.classList.add('arc-events-band-title'); + this.div.classList.add(className); if (opt_iconContent) { var icon = document.createElement('img'); icon.src = 'data:image/png;base64,' + opt_iconContent; @@ -210,8 +259,8 @@ this.div.appendChild(span); this.controlledItems = []; this.div.onclick = this.onClick_.bind(this); - var parent = $('arc-event-bands'); - parent.appendChild(this.div); + this.parent = parent; + this.parent.appendChild(this.div); } /** @@ -241,14 +290,18 @@ * @param {string} className class name of the svg element that represents * this band. 'arc-events-top-band' is used for top-level events and * 'arc-events-inner-band' is used for per-buffer events. - * @param {number} duration of bands in microseconds. + * @param {number} resolution the resolution of bands microseconds per 1 + * pixel. + * @param {number} minTimestamp the minimum timestamp to display on bands. + * @param {number} minTimestamp the maximum timestamp to display on bands. */ - constructor(title, className, duration) { + constructor(title, className, resolution, minTimestamp, maxTimestamp) { // Keep information about bands and their bounds. this.bands = []; this.globalEvents = []; - this.duration = duration; - this.width = timestampToOffset(duration); + this.resolution = resolution; + this.minTimestamp = minTimestamp; + this.maxTimestamp = maxTimestamp; this.height = 0; // Offset of the next band of events. this.nextYOffset = 0; @@ -256,14 +309,50 @@ this.svg.setAttributeNS( 'http://www.w3.org/2000/xmlns/', 'xmlns:xlink', 'http://www.w3.org/1999/xlink'); - this.svg.setAttribute('width', this.width + 'px'); + this.setBandOffsetX(0); + this.setWidth(0); this.svg.setAttribute('height', this.height + 'px'); this.svg.classList.add(className); this.setTooltip_(); title.addContolledItems(this.svg); - var parent = $('arc-event-bands'); - parent.appendChild(this.svg); + title.parent.appendChild(this.svg); + } + + /** + * Sets the horizontal offset to render bands. + * @param {number} offsetX offset in pixels. + */ + setBandOffsetX(offsetX) { + this.bandOffsetX = offsetX; + } + + /** + * Sets the widths of event bands. + * @param {number} width width in pixels. + */ + setWidth(width) { + this.width = width; + this.svg.setAttribute('width', this.width + 'px'); + } + + /** + * Converts timestamp into pixel offset. 1 pixel corresponds resolution + * microseconds. + * + * @param {number} timestamp in microseconds. + */ + timestampToOffset(timestamp) { + return (timestamp - this.minTimestamp) / this.resolution; + } + + /** + * Opposite conversion of |timestampToOffset| + * + * @param {number} offset in pixels. + */ + offsetToTime(offset) { + return offset * this.resolution + this.minTimestamp; } /** @@ -276,15 +365,14 @@ */ addBand(eventBand, height, padding) { var currentColor = bandColor; - var x = 0; - var eventIndex = -1; - while (true) { - eventIndex = eventBand.getNextEvent(eventIndex, 1 /* direction */); - if (eventIndex < 0) { + var x = this.bandOffsetX; + var eventIndex = eventBand.getFirstAfter(this.minTimestamp); + while (eventIndex >= 0) { + var event = eventBand.events[eventIndex]; + if (event[1] >= this.maxTimestamp) { break; } - var event = eventBand.events[eventIndex]; - var nextX = timestampToOffset(event[1]); + var nextX = this.timestampToOffset(event[1]) + this.bandOffsetX; SVG.addRect( this.svg, x, this.nextYOffset, nextX - x, height, currentColor); if (eventBand.isEndOfSequence(eventIndex)) { @@ -293,9 +381,12 @@ currentColor = eventAttributes[event[0]].color; } x = nextX; + eventIndex = eventBand.getNextEvent(eventIndex, 1 /* direction */); } SVG.addRect( - this.svg, x, this.nextYOffset, this.width - x, height, currentColor); + this.svg, x, this.nextYOffset, + this.timestampToOffset(this.maxTimestamp) - x + this.bandOffsetX, + height, currentColor); this.bands.push({ band: eventBand, @@ -323,7 +414,7 @@ } var event = events.events[eventIndex]; var attributes = events.getEventAttributes(eventIndex); - var x = timestampToOffset(event[1]); + var x = this.timestampToOffset(event[1]) + this.bandOffsetX; SVG.addLine( this.svg, x, 0, x, this.height, attributes.color, attributes.width); } @@ -332,10 +423,13 @@ /** Initializes tooltip support by observing mouse events */ setTooltip_() { - this.tooltip = getSVGElement('arc-event-band-tooltip'); + this.tooltip = $('arc-event-band-tooltip'); this.svg.onmouseover = this.showToolTip_.bind(this); this.svg.onmouseout = this.hideToolTip_.bind(this); this.svg.onmousemove = this.updateToolTip_.bind(this); + this.svg.onclick = (event) => { + showDetailedInfoForBand(this, event); + }; } /** Updates tooltip and shows it for this band. */ @@ -391,6 +485,12 @@ var lineHeight = 16; var fontSize = 12; + var offsetX = event.offsetX - this.bandOffsetX; + if (offsetX < 0) { + this.tooltip.classList.remove('active'); + return; + } + // Find band for this mouse event. var eventBand = undefined; @@ -407,10 +507,16 @@ return; } + var svg = document.createElementNS(svgNS, 'svg'); + svg.setAttributeNS( + 'http://www.w3.org/2000/xmlns/', 'xmlns:xlink', + 'http://www.w3.org/1999/xlink'); + this.tooltip.appendChild(svg); + var yOffset = verticalGap + lineHeight; - var eventTimestamp = offsetToTime(event.offsetX); + var eventTimestamp = this.offsetToTime(offsetX); SVG.addText( - this.tooltip, horizontalGap, yOffset, fontSize, + svg, horizontalGap, yOffset, fontSize, timestempToMsText(eventTimestamp) + ' ms'); yOffset += lineHeight; @@ -432,14 +538,15 @@ // Show the global event info. var attributes = eventAttributes[globalEvent[0]]; SVG.addText( - this.tooltip, horizontalGap, yOffset, 12, + svg, horizontalGap, yOffset, 12, attributes.name + ' ' + timestempToMsText(globalEvent[1]) + ' ms.'); } else if (index < 0 || eventBand.isEndOfSequence(index)) { // In case cursor points to idle event, show its interval. var startIdle = index < 0 ? 0 : eventBand.events[index][1]; - var endIdle = index < 0 ? this.duration : eventBand.events[nextIndex][1]; + var endIdle = + nextIndex < 0 ? this.maxTimestamp : eventBand.events[nextIndex][1]; SVG.addText( - this.tooltip, horizontalGap, yOffset, 12, + svg, horizontalGap, yOffset, 12, 'Idle ' + timestempToMsText(startIdle) + '...' + timestempToMsText(endIdle) + ' ms.'); yOffset += lineHeight; @@ -492,16 +599,19 @@ } for (var i = 0; i < entriesToShow.length; ++i) { var entryToShow = entriesToShow[i]; - SVG.addText( - this.tooltip, horizontalGap, yOffset, fontSize, entryToShow.prefix); + SVG.addText(svg, horizontalGap, yOffset, fontSize, entryToShow.prefix); SVG.addCircle( - this.tooltip, eventIconOffset, yOffset - eventIconRadius, - eventIconRadius, 1, entryToShow.color, 'black'); - SVG.addText( - this.tooltip, eventNameOffset, yOffset, fontSize, entryToShow.text); + svg, eventIconOffset, yOffset - eventIconRadius, eventIconRadius, 1, + entryToShow.color, 'black'); + SVG.addText(svg, eventNameOffset, yOffset, fontSize, entryToShow.text); yOffset += lineHeight; } } + if (this.canShowDetailedInfo()) { + SVG.addText( + svg, horizontalGap, yOffset, fontSize, 'Click for detailed info'); + yOffset += lineHeight; + } yOffset += verticalGap; this.tooltip.style.left = event.clientX + 'px'; @@ -509,16 +619,261 @@ this.tooltip.style.height = yOffset + 'px'; this.tooltip.classList.add('active'); } + + /** + * Returns true in case band can show detailed info. + */ + canShowDetailedInfo() { + return false; + } + + /** + * Shows detailed info for the position under mouse event |event|. By default + * it creates nothing. + */ + showDetailedInfo(event) { + return null; + } +} + +/** + * Base class for detailed info view. + */ +class DetailedInfoView { + discard() {} +} + +/** + * CPU detailed info view. Renders 4x zoomed CPU events split by processes and + * threads. + */ +class CpuDetailedInfoView extends DetailedInfoView { + create(overviewBand) { + this.overlay = $('arc-detailed-view-overlay'); + var overviewRect = overviewBand.svg.getBoundingClientRect(); + + // Clear previous content. + this.overlay.textContent = ''; + + // UI constants to render. + var columnWidth = 140; + var scrollBarWidth = 3; + var zoomFactor = 4.0; + var cpuBandHeight = 14; + var processInfoHeight = 14; + var padding = 2; + var fontSize = 12; + var processInfoPadding = 2; + var threadInfoPadding = 6; + + // Use minimum 80% of inner width or 600 pixels to display detailed view + // zoomed |zoomFactor| times. + var availableWidthPixels = + window.innerWidth * 0.8 - columnWidth - scrollBarWidth; + availableWidthPixels = Math.max(availableWidthPixels, 600); + var availableForHalfBandMcs = Math.floor( + overviewBand.offsetToTime(availableWidthPixels) / (2.0 * zoomFactor)); + // Determine the interval to display. + var eventTimestamp = + overviewBand.offsetToTime(event.offsetX - overviewBand.bandOffsetX); + var minTimestamp = eventTimestamp - availableForHalfBandMcs; + var maxTimestamp = eventTimestamp + availableForHalfBandMcs + 1; + var duration = maxTimestamp - minTimestamp; + + // Construct sub-model of active/idle events per each thread, active within + // this interval. + var eventsPerTid = {}; + for (var cpuId = 0; cpuId < overviewBand.model.cpu.events.length; cpuId++) { + var activeEvents = new Events( + overviewBand.model.cpu.events[cpuId], 3 /* kActive */, + 3 /* kActive */); + var activeTid = 0; + var index = activeEvents.getFirstAfter(minTimestamp); + var activeStartTimestamp = minTimestamp; + while (index >= 0 && activeEvents.events[index][1] < maxTimestamp) { + this.addActivityTime_( + eventsPerTid, activeTid, activeStartTimestamp, + activeEvents.events[index][1]); + activeTid = activeEvents.events[index][2]; + activeStartTimestamp = activeEvents.events[index][1]; + index = activeEvents.getNextEvent(index, 1 /* direction */); + } + this.addActivityTime_( + eventsPerTid, activeTid, activeStartTimestamp, maxTimestamp - 1); + } + + // The same thread might be executed on different CPU cores. Sort events. + for (var tid in eventsPerTid) { + eventsPerTid[tid].events.sort(function(a, b) { + return a[1] - b[1]; + }); + } + + // Group threads by process. + var threadsPerPid = {}; + var pids = []; + var totalTime = 0; + for (var tid in eventsPerTid) { + var thread = eventsPerTid[tid]; + var pid = overviewBand.model.cpu.threads[tid].pid; + if (!(pid in threadsPerPid)) { + pids.push(pid); + threadsPerPid[pid] = {}; + threadsPerPid[pid].totalTime = 0; + threadsPerPid[pid].threads = []; + } + threadsPerPid[pid].totalTime += thread.totalTime; + threadsPerPid[pid].threads.push(thread); + totalTime += thread.totalTime; + } + + // Sort processes per time usage. + pids.sort(function(a, b) { + return threadsPerPid[b].totalTime - threadsPerPid[a].totalTime; + }); + + var totalUsage = 100.0 * totalTime / duration; + var cpuInfo = 'CPU view. ' + pids.length + '/' + + Object.keys(eventsPerTid).length + + ' active processes/threads. Total cpu usage: ' + totalUsage.toFixed(2) + + '%.'; + var title = new EventBandTitle(this.overlay, cpuInfo, 'arc-cpu-view-title'); + var bands = new EventBands( + title, 'arc-events-cpu-detailed-band', + overviewBand.resolution / zoomFactor, minTimestamp, maxTimestamp); + bands.setBandOffsetX(columnWidth); + var bandsWidth = bands.timestampToOffset(maxTimestamp); + var totalWidth = bandsWidth + columnWidth; + bands.setWidth(totalWidth); + + for (i = 0; i < pids.length; i++) { + var pid = pids[i]; + var threads = threadsPerPid[pid].threads; + var processName; + if (pid in overviewBand.model.cpu.threads) { + processName = overviewBand.model.cpu.threads[pid].name; + } else { + processName = 'Others'; + } + bands.nextYOffset += (processInfoHeight + padding); + var processCpuUsage = 100.0 * threadsPerPid[pid].totalTime / duration; + var processInfo = processName + ' <' + pid + + '>, cpu usage: ' + processCpuUsage.toFixed(2) + '%.'; + SVG.addText( + bands.svg, processInfoPadding, bands.nextYOffset - 2 * padding, + fontSize, processInfo); + bands.svg.setAttribute('height', bands.nextYOffset + 'px'); + + // Sort threads per time usage. + threads.sort(function(a, b) { + return eventsPerTid[b.tid].totalTime - eventsPerTid[a.tid].totalTime; + }); + + for (j = 0; j < threads.length; j++) { + var tid = threads[j].tid; + bands.addBand( + new Events(eventsPerTid[tid].events, 0, 1), cpuBandHeight, padding); + var threadName = overviewBand.model.cpu.threads[tid].name; + var threadCpuUsage = 100.0 * threads[j].totalTime / duration; + var threadInfo = threadName + ' ' + threadCpuUsage.toFixed(2) + '%'; + SVG.addText( + bands.svg, threadInfoPadding, bands.nextYOffset - padding, fontSize, + threadInfo); + } + } + + // Add center and boundary lines. + var kTimeMark = 10000; + var timeEvents = [ + [kTimeMark, minTimestamp], [kTimeMark, eventTimestamp], + [kTimeMark, maxTimestamp - 1] + ]; + bands.addGlobal(new Events(timeEvents, kTimeMark, kTimeMark)); + + // Mark zoomed interval in overview. + var overviewX = overviewBand.timestampToOffset(minTimestamp); + var overviewWidth = + overviewBand.timestampToOffset(maxTimestamp) - overviewX; + this.bandSelection = SVG.addRect( + overviewBand.svg, overviewX, 0, overviewWidth, overviewBand.height, + '#000' /* color */, 0.1 /* opacity */); + + // Align position in overview and middle line here if possible. + var left = Math.max( + Math.min( + Math.round(event.clientX - columnWidth - bandsWidth * 0.5), + window.innerWidth - totalWidth), + 0); + this.overlay.style.left = left + 'px'; + // Place below the overview with small gap. + this.overlay.style.top = (overviewRect.bottom + window.scrollY + 2) + 'px'; + this.overlay.classList.add('active'); + } + + discard() { + this.overlay.classList.remove('active'); + this.bandSelection.remove(); + } + + /** + * Helper that adds kIdleIn/kIdle events into the dictionary. + * + * @param {Object} eventsPerTid dictionary to fill. Key is thread id and + * value is object that contains all events for thread with related + * information. + * @param {number} tid thread id. + * @param {number} timestampFrom start time of thread activity. + * @param {number} timestampTo end time of thread activity. + */ + addActivityTime_(eventsPerTid, tid, timestampFrom, timestampTo) { + if (tid == 0) { + // Don't process idle thread. + return; + } + if (!(tid in eventsPerTid)) { + // Create the band for the new thread. + eventsPerTid[tid] = {}; + eventsPerTid[tid].totalTime = 0; + eventsPerTid[tid].events = []; + eventsPerTid[tid].tid = tid; + } + eventsPerTid[tid].events.push([1 /* kIdleOut */, timestampFrom]); + eventsPerTid[tid].events.push([0 /* kIdleIn */, timestampTo]); + // Update total time for this thread. + eventsPerTid[tid].totalTime += (timestampTo - timestampFrom); + } +} + +class CpuEventBands extends EventBands { + setModel(model) { + this.model = model; + var bandHeight = 6; + var padding = 2; + for (var cpuId = 0; cpuId < this.model.cpu.events.length; cpuId++) { + this.addBand( + new Events(this.model.cpu.events[cpuId], 0, 1), bandHeight, padding); + } + } + + canShowDetailedInfo() { + return true; + } + + showDetailedInfo(event) { + var view = new CpuDetailedInfoView(); + view.create(this); + return view; + } } /** Represents one band with events. */ class Events { /** - * Assigns events for this band. Events with type between |eventTypeMin| - * and |eventTypeMax| are only displayed on the band. + * Assigns events for this band. Events with type between |eventTypeMin| and + * |eventTypeMax| are only displayed on the band. * - * @param {Object[]} events non-filtered list of all events. Each has - * array where first element is type and second is timestamp. + * @param {Object[]} events non-filtered list of all events. Each has array + * where first element is type and second is timestamp. * @param {number} eventTypeMin minimum inclusive type of the event to be * displayed on this band. * @param {number} eventTypeMax maximum inclusive type of the event to be @@ -535,10 +890,10 @@ * only processed. * * @param {number} index starting index for the search, not inclusive. - * @param {direction} direction to search, 1 means to find the next event - * and -1 means the previous event. - * @returns {number} index of the next or previous event or -1 in case - * not found. + * @param {direction} direction to search, 1 means to find the next event and + * -1 means the previous event. + * @returns {number} index of the next or previous event or -1 in case not + * found. */ getNextEvent(index, direction) { while (true) { @@ -629,6 +984,22 @@ } } } + + /** + * Returns the index of the first event after or on requested |timestamp|. + * + * @param {number} timestamp to search. + */ + getFirstAfter(timestamp) { + var closest = this.getClosest(timestamp); + if (closest < 0) { + return -1; + } + if (this.events[closest][1] >= timestamp) { + return closest; + } + return this.getNextEvent(closest, 1 /* direction */); + } } /** @@ -640,27 +1011,48 @@ // Clear previous content. $('arc-event-bands').textContent = ''; + // Microseconds per pixel. + var resolution = 100.0; + var parent = $('arc-event-bands'); + + var topBandHeight = 16; + var topBandPadding = 4; + var innerBandHeight = 12; + var innerBandPadding = 2; + var innerLastBandPadding = 12; + + var cpusTitle = new EventBandTitle(parent, 'CPUs', 'arc-events-band-title'); + var cpusBands = new CpuEventBands( + cpusTitle, 'arc-events-band', resolution, 0, model.duration); + cpusBands.setWidth(cpusBands.timestampToOffset(model.duration)); + cpusBands.setModel(model); + var vsyncEvents = new Events( model.android.global_events, 400 /* kVsync */, 400 /* kVsync */); - var chromeTitle = new EventBandTitle('Chrome'); - var chromeBands = - new EventBands(chromeTitle, 'arc-events-top-band', model.duration); + var chromeTitle = + new EventBandTitle(parent, 'Chrome graphics', 'arc-events-band-title'); + var chromeBands = new EventBands( + chromeTitle, 'arc-events-band', resolution, 0, model.duration); + chromeBands.setWidth(chromeBands.timestampToOffset(model.duration)); for (i = 0; i < model.chrome.buffers.length; i++) { chromeBands.addBand( - new Events(model.chrome.buffers[i], 500, 599), 20 /* height */, - 4 /* padding */); + new Events(model.chrome.buffers[i], 500, 599), topBandHeight, + topBandPadding); } + chromeBands.addGlobal(new Events( model.chrome.global_events, 505 /* kChromeOSJank */, 505 /* kChromeOSJank */)); - var androidTitle = new EventBandTitle('Android'); - var androidBands = - new EventBands(androidTitle, 'arc-events-top-band', model.duration); + var androidTitle = + new EventBandTitle(parent, 'Android graphics', 'arc-events-band-title'); + var androidBands = new EventBands( + androidTitle, 'arc-events-band', resolution, 0, model.duration); + androidBands.setWidth(androidBands.timestampToOffset(model.duration)); androidBands.addBand( - new Events(model.android.buffers[0], 400, 499), 20 /* height */, - 0 /* padding */); + new Events(model.android.buffers[0], 400, 499), topBandHeight, + topBandPadding); // Add vsync events androidBands.addGlobal(vsyncEvents); androidBands.addGlobal(new Events( @@ -678,24 +1070,23 @@ } else { activityTitleText = 'Task #' + view.task_id + ' - ' + view.activity; } - var activityTitle = new EventBandTitle(activityTitleText, icon); - var activityBands = - new EventBands(activityTitle, 'arc-events-inner-band', model.duration); + var activityTitle = new EventBandTitle( + parent, activityTitleText, 'arc-events-band-title', icon); + var activityBands = new EventBands( + activityTitle, 'arc-events-band', resolution, 0, model.duration); + activityBands.setWidth(activityBands.timestampToOffset(model.duration)); for (j = 0; j < view.buffers.length; j++) { - var androidBand = new Events( - activityTitle, 'arc-events-inner-band', model.duration, 14); + var androidBand = + new Events(activityTitle, 'arc-events-band', model.duration, 14); // Android buffer events. activityBands.addBand( - new Events(view.buffers[j], 100, 199), 14 /* height */, - 4 /* padding */); + new Events(view.buffers[j], 100, 199), innerBandHeight, + innerBandPadding); // exo events. activityBands.addBand( - new Events(view.buffers[j], 200, 299), 14 /* height */, - 4 /* padding */); - // Chrome buffer events. - activityBands.addBand( - new Events(view.buffers[j], 300, 399), 14 /* height */, - 12 /* padding */); + new Events(view.buffers[j], 200, 299), innerBandHeight, + innerLastBandPadding); + // Chrome buffer events are not displayed at this time. } // Add vsync events activityBands.addGlobal(vsyncEvents);
diff --git a/chrome/browser/resources/chromeos/os_settings.html b/chrome/browser/resources/chromeos/os_settings.html new file mode 100644 index 0000000..0cf91ae --- /dev/null +++ b/chrome/browser/resources/chromeos/os_settings.html
@@ -0,0 +1,7 @@ +<!doctype html> +<html> +<!-- TODO(jamescook): Text direction, language, title, etc. --> +<body> + Hello, settings! +</body> +</html>
diff --git a/chrome/browser/resources/local_ntp/BUILD.gn b/chrome/browser/resources/local_ntp/BUILD.gn new file mode 100644 index 0000000..f7d4bd9 --- /dev/null +++ b/chrome/browser/resources/local_ntp/BUILD.gn
@@ -0,0 +1,28 @@ +# 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_type_check("closure_compile") { + deps = [ + ":local_ntp", + ] +} + +js_library("local_ntp") { + sources = [ + "animations.js", + "custom_backgrounds.js", + "custom_links_edit.js", + "doodles.js", + "instant_iframe_validation.js", + "local_ntp.js", + "most_visited_single.js", + "most_visited_title.js", + "most_visited_util.js", + "utils.js", + "voice.js", + ] + externs_list = [ "externs.js" ] +}
diff --git a/chrome/browser/resources/local_ntp/custom_backgrounds.js b/chrome/browser/resources/local_ntp/custom_backgrounds.js index 63f8059..73bf1f7 100644 --- a/chrome/browser/resources/local_ntp/custom_backgrounds.js +++ b/chrome/browser/resources/local_ntp/custom_backgrounds.js
@@ -48,7 +48,7 @@ /** * Enum for key codes. - * @enum {int} + * @enum {number} * @const */ customBackgrounds.KEYCODES = { @@ -134,7 +134,7 @@ /** * Enum for background sources. - * @enum {int} + * @enum {number} * @const */ customBackgrounds.SOURCES = { @@ -145,7 +145,7 @@ /** * Enum for background option menu entries, in the order they appear in the UI. - * @enum {int} + * @enum {number} * @const */ customBackgrounds.MENU_ENTRIES = { @@ -177,7 +177,7 @@ /* Type of collection that is being browsed, needed in order * to return from the image dialog. - * @type {int} + * @type {number} */ customBackgrounds.dialogCollectionsSource = customBackgrounds.SOURCES.NONE; @@ -186,14 +186,14 @@ * @type {?Function} * @private */ -customBackgrounds.showErrorNotification; +customBackgrounds.showErrorNotification = null; /* * Called when the custom link notification should be hidden. * @type {?Function} * @private */ -customBackgrounds.hideCustomLinkNotification; +customBackgrounds.hideCustomLinkNotification = null; /** * Sets the visibility of the settings menu and individual options depending on @@ -308,7 +308,7 @@ tile.style.backgroundImage = 'url(' + data.previewImageUrl + ')'; tile.dataset.id = data.collectionId; tile.dataset.name = data.collectionName; - fadeInImageTile(tile, data.previewImageUrl); + fadeInImageTile(tile, data.previewImageUrl, null); return tile; }; @@ -331,8 +331,8 @@ /* Get the next tile when the arrow keys are used to navigate the grid. * Returns null if the tile doesn't exist. - * @param {int} deltaX Change in the x direction. - * @param {int} deltaY Change in the y direction. + * @param {number} deltaX Change in the x direction. + * @param {number} deltaY Change in the y direction. * @param {string} current Number of the current tile. */ customBackgrounds.getNextTile = function(deltaX, deltaY, current) { @@ -343,10 +343,10 @@ } if (deltaX != 0) { - let target = parseInt(current) + deltaX; + let target = parseInt(current, /*radix=*/ 10) + deltaX; return $(idPrefix + target); } else if (deltaY != 0) { - let target = parseInt(current); + let target = parseInt(current, /*radix=*/ 10); let nextTile = $(idPrefix + target); let startingTop = nextTile.getBoundingClientRect().top; let startingLeft = nextTile.getBoundingClientRect().left; @@ -364,7 +364,7 @@ /** * Show dialog for selecting a Chrome background. - * @param {int} collectionsSource The enum value of the source to fetch + * @param {number} collectionsSource The enum value of the source to fetch * collection data from. */ customBackgrounds.showCollectionSelectionDialog = function(collectionsSource) { @@ -429,8 +429,7 @@ imgScript.onload = function() { // Verify that the individual image data was successfully loaded. var imageDataLoaded = - (coll_img.length > 0 && - coll_img[0].collectionId == tile.dataset.id); + (collImg.length > 0 && collImg[0].collectionId == tile.dataset.id); // Dependent upon the success of the load, populate the image selection // dialog or close the current dialog. @@ -438,7 +437,7 @@ customBackgrounds.resetSelectionDialog(); customBackgrounds.showImageSelectionDialog(tile.dataset.name); } else { - customBackgrounds.handleError(coll_img_errors); + customBackgrounds.handleError(collImgErrors); } }; }; @@ -462,20 +461,22 @@ if (event.keyCode === customBackgrounds.KEYCODES.LEFT) { target = customBackgrounds.getNextTile( document.documentElement.classList.contains('rtl') ? 1 : -1, 0, - this.dataset.tile_num); + event.currentTarget.dataset.tile_num); } else if (event.keyCode === customBackgrounds.KEYCODES.UP) { - target = customBackgrounds.getNextTile(0, -1, this.dataset.tile_num); + target = customBackgrounds.getNextTile( + 0, -1, event.currentTarget.dataset.tile_num); } else if (event.keyCode === customBackgrounds.KEYCODES.RIGHT) { target = customBackgrounds.getNextTile( document.documentElement.classList.contains('rtl') ? -1 : 1, 0, - this.dataset.tile_num); + event.currentTarget.dataset.tile_num); } else if (event.keyCode === customBackgrounds.KEYCODES.DOWN) { - target = customBackgrounds.getNextTile(0, 1, this.dataset.tile_num); + target = customBackgrounds.getNextTile( + 0, 1, event.currentTarget.dataset.tile_num); } if (target) { target.focus(); } else { - this.focus(); + event.currentTarget.focus(); } } }; @@ -490,7 +491,7 @@ /** * Apply border and checkmark when a tile is selected - * @param {div} tile The tile to apply styling to. + * @param {!Element} tile The tile to apply styling to. */ customBackgrounds.applySelectedState = function(tile) { tile.classList.add(customBackgrounds.CLASSES.COLLECTION_SELECTED); @@ -511,7 +512,7 @@ /** * Remove border and checkmark when a tile is un-selected - * @param {div} tile The tile to remove styling from. + * @param {!Element} tile The tile to remove styling from. */ customBackgrounds.removeSelectedState = function(tile) { tile.classList.remove(customBackgrounds.CLASSES.COLLECTION_SELECTED); @@ -521,7 +522,7 @@ /** * Show dialog for selecting an image. Image data should previous have been - * loaded into coll_img via + * loaded into collImg via * chrome-search://local-ntp/ntp-background-images.js?collection_id=<collection_id> * @param {string} dialogTitle The title to be displayed at the top of the * dialog. @@ -539,7 +540,7 @@ let preLoadTiles = []; let postLoadTiles = []; - for (var i = 0; i < coll_img.length; ++i) { + for (var i = 0; i < collImg.length; ++i) { let tileBackground = document.createElement('div'); tileBackground.classList.add( customBackgrounds.CLASSES.COLLECTION_TILE_BG); @@ -550,23 +551,23 @@ // TODO(crbug.com/854028): Remove this hardcoded check when wallpaper // previews are supported. - if (coll_img[i].collectionId === 'solidcolors') { + if (collImg[i].collectionId === 'solidcolors') { tile.dataset.attributionLine1 = ''; tile.dataset.attributionLine2 = ''; tile.dataset.attributionActionUrl = ''; } else { tile.dataset.attributionLine1 = - (coll_img[i].attributions[0] !== undefined ? - coll_img[i].attributions[0] : + (collImg[i].attributions[0] !== undefined ? + collImg[i].attributions[0] : ''); tile.dataset.attributionLine2 = - (coll_img[i].attributions[1] !== undefined ? - coll_img[i].attributions[1] : + (collImg[i].attributions[1] !== undefined ? + collImg[i].attributions[1] : ''); - tile.dataset.attributionActionUrl = coll_img[i].attributionActionUrl; + tile.dataset.attributionActionUrl = collImg[i].attributionActionUrl; } - tile.setAttribute('aria-label', coll_img[i].attributions[0]); - tile.dataset.url = coll_img[i].imageUrl; + tile.setAttribute('aria-label', collImg[i].attributions[0]); + tile.dataset.url = collImg[i].imageUrl; tile.id = 'img_tile_' + i; tile.dataset.tile_num = i; @@ -604,11 +605,15 @@ let clickCount = event.detail; // Control + option + space will fire the onclick event with 0 clickCount. if (clickCount <= 1) { - tileInteraction(this); - } else if (clickCount === 2 && customBackgrounds.selectedTile === this) { - customBackgrounds.setBackground(this.dataset.url, - this.dataset.attributionLine1, this.dataset.attributionLine2, - this.dataset.attributionActionUrl); + tileInteraction(event.currentTarget); + } else if ( + clickCount === 2 && + customBackgrounds.selectedTile === event.currentTarget) { + customBackgrounds.setBackground( + event.currentTarget.dataset.url, + event.currentTarget.dataset.attributionLine1, + event.currentTarget.dataset.attributionLine2, + event.currentTarget.dataset.attributionActionUrl); } }; tile.onkeydown = function(event) { @@ -616,7 +621,7 @@ if (event.keyCode === customBackgrounds.KEYCODES.ENTER) { event.preventDefault(); event.stopPropagation(); - tileInteraction(this); + tileInteraction(event.currentTarget); } else if ( event.keyCode === customBackgrounds.KEYCODES.LEFT || event.keyCode === customBackgrounds.KEYCODES.UP || @@ -630,20 +635,22 @@ if (event.keyCode == customBackgrounds.KEYCODES.LEFT) { target = customBackgrounds.getNextTile( document.documentElement.classList.contains('rtl') ? 1 : -1, 0, - this.dataset.tile_num); + event.currentTarget.dataset.tile_num); } else if (event.keyCode == customBackgrounds.KEYCODES.UP) { - target = customBackgrounds.getNextTile(0, -1, this.dataset.tile_num); + target = customBackgrounds.getNextTile( + 0, -1, event.currentTarget.dataset.tile_num); } else if (event.keyCode == customBackgrounds.KEYCODES.RIGHT) { target = customBackgrounds.getNextTile( document.documentElement.classList.contains('rtl') ? -1 : 1, 0, - this.dataset.tile_num); + event.currentTarget.dataset.tile_num); } else if (event.keyCode == customBackgrounds.KEYCODES.DOWN) { - target = customBackgrounds.getNextTile(0, 1, this.dataset.tile_num); + target = customBackgrounds.getNextTile( + 0, 1, event.currentTarget.dataset.tile_num); } if (target) { target.focus(); } else { - this.focus(); + event.currentTarget.focus(); } } }; @@ -653,11 +660,11 @@ } let tileGetsLoaded = 0; for (let tile of preLoadTiles) { - loadTile(tile, coll_img, () => { + loadTile(tile, collImg, () => { // After the preloaded tiles finish loading, the rest of the tiles start // loading. if (++tileGetsLoaded === preLoadTiles.length) { - postLoadTiles.forEach((tile) => loadTile(tile, coll_img)); + postLoadTiles.forEach((tile) => loadTile(tile, collImg, null)); } }); } @@ -668,8 +675,8 @@ /** * Add background image src to the tile and add animation for the tile once it * successfully loaded. - * @param {Object} tile the tile that needs to be loaded. - * @param {object} imageData the source imageData. + * @param {!Object} tile the tile that needs to be loaded. + * @param {!Object} imageData the source imageData. * @param {?Function} countLoad If not null, called after the tile finishes * loading. */ @@ -690,7 +697,7 @@ * Fade in effect for both collection and image tile. Once the image * successfully loads, we can assume the background image with the same source * has also loaded. Then, we set opacity for the tile to start the animation. - * @param {Object} tile The tile to add the fade in animation to. + * @param {!Object} tile The tile to add the fade in animation to. * @param {string} imageUrl the image url for the tile * @param {?Function} countLoad If not null, called after the tile finishes * loading. @@ -731,8 +738,8 @@ /* * Get the next visible option. There are times when various combinations of * options are hidden. - * @param {int} current_index Index of the option the key press occurred on. - * @param {int} deltaY Direction to search in, -1 for up, 1 for down. + * @param {number} current_index Index of the option the key press occurred on. + * @param {number} deltaY Direction to search in, -1 for up, 1 for down. */ customBackgrounds.getNextOption = function(current_index, deltaY) { // Create array corresponding to the menu. Important that this is in the same @@ -895,7 +902,7 @@ $(customBackgrounds.IDS.CUSTOM_LINKS_RESTORE_DEFAULT).onkeydown = function( event) { if (event.keyCode === customBackgrounds.KEYCODES.ENTER) { - customLinksRestoreDefaultInteraction(event); + customLinksRestoreDefaultInteraction(); } else if (event.keyCode === customBackgrounds.KEYCODES.UP) { // Handle arrow key navigation. event.preventDefault(); @@ -960,21 +967,21 @@ $(customBackgrounds.IDS.DONE).disabled = true; // Interactions with the "Upload an image" option. - var uploadImageInteraction = function(event) { + var uploadImageInteraction = function() { window.chrome.embeddedSearch.newTabPage.selectLocalBackgroundImage(); ntpApiHandle.logEvent( BACKGROUND_CUSTOMIZATION_LOG_TYPE.NTP_CUSTOMIZE_LOCAL_IMAGE_CLICKED); }; - $(customBackgrounds.IDS.UPLOAD_IMAGE).onclick = () => { + $(customBackgrounds.IDS.UPLOAD_IMAGE).onclick = (event) => { if (!$(customBackgrounds.IDS.UPLOAD_IMAGE).classList.contains( customBackgrounds.CLASSES.OPTION_DISABLED)) { uploadImageInteraction(); } - } ; + }; $(customBackgrounds.IDS.UPLOAD_IMAGE).onkeydown = function(event) { if (event.keyCode === customBackgrounds.KEYCODES.ENTER) { - uploadImageInteraction(event); + uploadImageInteraction(); } // Handle arrow key navigation. @@ -993,14 +1000,14 @@ }; // Interactions with the "Restore default background" option. - var restoreDefaultInteraction = function(event) { + var restoreDefaultInteraction = function() { editDialog.close(); customBackgrounds.clearAttribution(); window.chrome.embeddedSearch.newTabPage.setBackgroundURL(''); ntpApiHandle.logEvent(BACKGROUND_CUSTOMIZATION_LOG_TYPE .NTP_CUSTOMIZE_RESTORE_BACKGROUND_CLICKED); }; - $(customBackgrounds.IDS.RESTORE_DEFAULT).onclick = () => { + $(customBackgrounds.IDS.RESTORE_DEFAULT).onclick = (event) => { if (!$(customBackgrounds.IDS.RESTORE_DEFAULT).classList.contains( customBackgrounds.CLASSES.OPTION_DISABLED)) { restoreDefaultInteraction(); @@ -1008,7 +1015,7 @@ }; $(customBackgrounds.IDS.RESTORE_DEFAULT).onkeydown = function(event) { if (event.keyCode === customBackgrounds.KEYCODES.ENTER) { - restoreDefaultInteraction(event); + restoreDefaultInteraction(); } // Handle arrow key navigation. @@ -1035,13 +1042,13 @@ customBackgrounds.showCollectionSelectionDialog( customBackgrounds.SOURCES.CHROME_BACKGROUNDS); } else { - customBackgrounds.handleError(coll_errors); + customBackgrounds.handleError(collErrors); } }; ntpApiHandle.logEvent(BACKGROUND_CUSTOMIZATION_LOG_TYPE .NTP_CUSTOMIZE_CHROME_BACKGROUNDS_CLICKED); }; - $(customBackgrounds.IDS.DEFAULT_WALLPAPERS).onclick = function() { + $(customBackgrounds.IDS.DEFAULT_WALLPAPERS).onclick = function(event) { $(customBackgrounds.IDS.MENU) .classList.add(customBackgrounds.CLASSES.MOUSE_NAV); defaultWallpapersInteraction(event);
diff --git a/chrome/browser/resources/local_ntp/custom_links_edit.js b/chrome/browser/resources/local_ntp/custom_links_edit.js index 541b7ce3..afb18410 100644 --- a/chrome/browser/resources/local_ntp/custom_links_edit.js +++ b/chrome/browser/resources/local_ntp/custom_links_edit.js
@@ -179,7 +179,7 @@ // Small delay to allow the dialog to close before cleaning up. window.setTimeout(() => { $(IDS.FORM).reset(); - $(IDS.TITLE_FIELD).dir = null; + $(IDS.TITLE_FIELD).dir = ''; $(IDS.URL_FIELD_CONTAINER).classList.remove('invalid'); $(IDS.DELETE).disabled = false; $(IDS.DONE).disabled = false; @@ -210,7 +210,7 @@ /** * Handler for the 'updateTheme' message from the host page. - * @param {object} info Data received in the message. + * @param {!Object} info Data received in the message. */ function updateTheme(info) { document.documentElement.setAttribute('darkmode', info.isDarkMode);
diff --git a/chrome/browser/resources/local_ntp/doodles.js b/chrome/browser/resources/local_ntp/doodles.js index 9632a18..bfb601d 100644 --- a/chrome/browser/resources/local_ntp/doodles.js +++ b/chrome/browser/resources/local_ntp/doodles.js
@@ -275,7 +275,7 @@ console.log(error); return; } - doodles.handleDdllogResponse(json.ddllog, isAnimated); + doodles.handleDdllogResponse(json['ddllog'], isAnimated); }) .catch(function(error) { console.log('Error logging doodle impression to "' + logUrl + '":'); @@ -294,7 +294,7 @@ * Logs a doodle sharing event. * Uses the ct param provided in metadata.onClickUrl to track the doodle. * - * @param {string} platform Social media platform the doodle will be shared to. + * @param {number} platform Social media platform the doodle will be shared to. */ doodles.logDoodleShare = function(platform) { if (doodles.targetDoodle.metadata.onClickUrl) { @@ -305,7 +305,7 @@ url.searchParams.append('atyp', 'i'); url.searchParams.append('ct', 'doodle'); url.searchParams.append('cad', 'sh,' + platform + ',ct:' + ct); - url.searchParams.append('ntp', 1); + url.searchParams.append('ntp', '1'); if (doodles.ei && doodles.ei != '') { url.searchParams.append('ei', doodles.ei); } @@ -422,17 +422,17 @@ * Starts fading out the given element, which should be either the default logo * or the doodle. * - * @param {HTMLElement} element + * @param {?Element} element */ doodles.startFadeOut = function(element) { - if (!element.classList.contains(doodles.CLASSES.SHOW_LOGO)) { + if (!element || !element.classList.contains(doodles.CLASSES.SHOW_LOGO)) { return; } // Compute style now, to ensure that the transition from 1 -> 0 is properly // recognized. Otherwise, if a 0 -> 1 -> 0 transition is too fast, the // element might stay invisible instead of appearing then fading out. - window.getComputedStyle(element).opacity; + const style = window.getComputedStyle(element).opacity; element.classList.add(doodles.CLASSES.FADE); element.classList.remove(doodles.CLASSES.SHOW_LOGO); @@ -475,7 +475,8 @@ $(doodles.IDS.LOGO_DEFAULT).classList.add(doodles.CLASSES.FADE); doodles.showLogoOrDoodle(/*fromCache=*/ false); - this.removeEventListener('transitionend', doodles.onDoodleFadeOutComplete); + e.target.removeEventListener( + 'transitionend', doodles.onDoodleFadeOutComplete); }; @@ -498,7 +499,8 @@ // Ping the static interaction_log_url if there is one. if (doodles.targetDoodle.staticInteractionLogUrl) { - navigator.sendBeacon(doodles.targetDoodle.staticInteractionLogUrl); + navigator.sendBeacon( + doodles.targetDoodle.staticInteractionLogUrl.href); doodles.targetDoodle.staticInteractionLogUrl = null; } @@ -520,7 +522,8 @@ // Ping the static interaction_log_url if there is one. if (doodles.targetDoodle.staticInteractionLogUrl) { - navigator.sendBeacon(doodles.targetDoodle.staticInteractionLogUrl); + navigator.sendBeacon( + doodles.targetDoodle.staticInteractionLogUrl.href); doodles.targetDoodle.staticInteractionLogUrl = null; } @@ -541,7 +544,7 @@ // Ping the animated interaction_log_url if there is one. if (doodles.targetDoodle.animatedInteractionLogUrl) { navigator.sendBeacon( - doodles.targetDoodle.animatedInteractionLogUrl); + doodles.targetDoodle.animatedInteractionLogUrl.href); doodles.targetDoodle.animatedInteractionLogUrl = null; }
diff --git a/chrome/browser/resources/local_ntp/externs.js b/chrome/browser/resources/local_ntp/externs.js new file mode 100644 index 0000000..8b3735d --- /dev/null +++ b/chrome/browser/resources/local_ntp/externs.js
@@ -0,0 +1,381 @@ +// 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 Externs for objects sent from C++ to + * chrome-search://local-ntp/local-ntp.html. + * @externs + */ + +/** + * The type of the most visited data object. The definition is based on + * chrome/common/search/instant_types.h: + * InstantMostVisitedItem + * @typedef {{dataGenerationTime: Date, + * isAddButton: boolean, + * tid: number, + * tileSource: number, + * tileTitleSource: number, + * title: ?, + * url: string}} + */ +let MostVisitedData; + +/** + * The type of the config data object. The definition is based on + * chrome/browser/search/local_ntp_source.cc: + * LocalNtpSource::SearchConfigurationProvider::UpdateConfigData() + * @typedef {{translatedStrings: Array<string>, + * isGooglePage: boolean, + * googleBaseUrl: string, + * isAccessibleBrowser: boolean, + * removeFakebox: boolean, + * alternateFakebox: boolean, + * fakeboxSearchIcon: boolean, + * hideShortcuts: boolean}} + */ +let configData; + +/** + * The type of the image collections object. The definition is based on + * chrome/browser/search/local_ntp_source.cc: + * ConvertCollectionInfoToDict() + * @typedef {{collectionId: string, + * collectionName: string, + * previewImageUrl: string}} + */ +let coll; + +/** + * The type of the individual image data object. The definition is based on + * chrome/browser/search/local_ntp_source.cc: + * ConvertCollectionImageToDict() + * @typedef {{thumbnailImageUrl: string, + * imageUrl: string, + * collectionId: string, + * attributions: Array<string>, + * attributionActionUrl: string}} + */ +let collImg; + +/** + * The type of the errors when fetching individual images object. The + * definition is based on + * chrome/browser/search/local_ntp_source.cc: + * GetErrorDict() + * @typedef {{net_error: boolean, + * service_error: boolean, + * net_error_no: number}} + */ +let collImgErrors; + +/** + * The type of the errors when fetching collection object. The definition is + * based on + * chrome/browser/search/local_ntp_source.cc: + * GetErrorDict() + * @typedef {{net_error: boolean, + * service_error: boolean, + * net_error_no: number}} + */ +let collErrors; + +/** + * The type of the Doodle data object. The definition is based on + * chrome/browser/search/local_ntp_source.cc: + * LocalNtpSource::DesktopLogoObserver::OnLogoAvailable() + * @typedef {{usable: boolean, + * image: string, + * metadata: string}} + */ +let ddl; + +/** + * The type of the OneGoogleBar data object. The definition is based on + * chrome/browser/search/local_ntp_source.cc: + * ConvertOGBDataToDict() + * @typedef {{barHtml: string, + * inHeadScript: string, + * inHeadStyle: string, + * afterBarScript: string, + * endOfBodyHtml: string, + * endOfBodyScript: string}} + */ +let og; + +/** + * The type of the middle-slot promo data object. The definition is based on + * chrome/browser/search/local_ntp_source.cc: + * ConvertPromoDataToDict() + * @typedef {{promoHtml: string, + * promoLogUrl: string}} + */ +let promo; + +/** + * The type of the search suggestions data object. The definition is based on + * chrome/browser/search/local_ntp_source.cc: + * ConvertSearchSuggestDataToDict() + * @typedef {{suggestionsHtml: string, + * suggestionsEndOfBodyScript: string}} + */ +let searchSuggestions; + +/** + * Types created by the OneGoogleBar scripts when injected into the page. + * Defined in google3/javascript/externs/api/one_google/gbar.js + */ +window.gbar; +window.gbar.a; +window.gbar.a.pc; + +/** + * Used for running NTP javascript unit tests. Defined in + * src/chrome/test/data/local_ntp/local_ntp_browsertest.html + */ +window.localNTPUnitTest; + +/**************************** Embedded Search API ****************************/ + +/** + * Embedded Search API methods defined in + * chrome/renderer/searchbox/searchbox_extension.cc: + * NewTabPageBindings::GetObjectTemplateBuilder() + */ + +window.chrome; +window.chrome.embeddedSearch; +window.chrome.embeddedSearch.newTabPage; + +/** + * @param {number} task_version + * @param {number} task_id + */ +window.chrome.embeddedSearch.newTabPage.blacklistSearchSuggestion; + +/** + * @param {number} task_version + * @param {number} task_id + * @param {string} hash + */ +window.chrome.embeddedSearch.newTabPage.blacklistSearchSuggestionWithHash; + +/** + * @param {string} identity + */ +window.chrome.embeddedSearch.newTabPage.checkIsUserSignedIntoChromeAs; + +/** + * No params. + */ +window.chrome.embeddedSearch.newTabPage.checkIsUserSyncingHistory; + +/** + * @param {number} tid + */ +window.chrome.embeddedSearch.newTabPage.deleteMostVisitedItem; + +/** + * @param {string} url + */ +window.chrome.embeddedSearch.newTabPage.fixupAndValidateUrl; + +/** + * @param {number} tid + */ +window.chrome.embeddedSearch.newTabPage.getMostVisitedItemData; + +/** + * @return {boolean} isCustomLinks + */ +window.chrome.embeddedSearch.newTabPage.isCustomLinks; + +/** + * @return {boolean} isInputInProgress + */ +window.chrome.embeddedSearch.newTabPage.isInputInProgress; + +/** + * @param {number} event + */ +window.chrome.embeddedSearch.newTabPage.logEvent; + +/** + * @param {number} position + * @param {number} tile_title_source + * @param {number} tile_source + * @param {number} tile_type + * @param {number} data_generation_time + */ +window.chrome.embeddedSearch.newTabPage.logMostVisitedImpression; + +/** + * @param {number} position + * @param {number} tile_title_source + * @param {number} tile_source + * @param {number} tile_type + * @param {number} data_generation_time + */ +window.chrome.embeddedSearch.newTabPage.logMostVisitedNavigation; + +/** + * No params. + */ +window.chrome.embeddedSearch.newTabPage.mostVisited; + +/** + * @return {boolean} mostVisitedAvailable + */ +window.chrome.embeddedSearch.newTabPage.mostVisitedAvailable; + +/** + * No params. + */ +window.chrome.embeddedSearch.newTabPage.optOutOfSearchSuggestions; + +/** + * @param {number} rid + * @param {number} new_pos + */ +window.chrome.embeddedSearch.newTabPage.reorderCustomLink; + +/** + * No params. + */ +window.chrome.embeddedSearch.newTabPage.resetCustomLinks; + +/** + * @param {number} task_version + * @param {number} task_id + * @param {string} hash + */ +window.chrome.embeddedSearch.newTabPage.searchSuggestionSelected; + +/** + * No params. + */ +window.chrome.embeddedSearch.newTabPage.selectLocalBackgroundImage; + +/** + * @param {string} background_url + */ +window.chrome.embeddedSearch.newTabPage.setBackgroundURL; + +/** + * @param {string} background_url + * @param {string} attribution_line_1 + * @param {string} attribution_line_2 + * @param {string} attribution_action_url + */ +window.chrome.embeddedSearch.newTabPage.setBackgroundURLWithAttributions; + +/** + * @return {Object} theme_background_info + */ +window.chrome.embeddedSearch.newTabPage.themeBackgroundInfo; + +/** + * No params. + */ +window.chrome.embeddedSearch.newTabPage.undoAllMostVisitedDeletions; + +/** + * No params. + */ +window.chrome.embeddedSearch.newTabPage.undoCustomLinkAction; + +/** + * @param {number} rid_value + */ +window.chrome.embeddedSearch.newTabPage.undoMostVisitedDeletion; + +/** + * @param {number} rid + * @param {string} url + */ +window.chrome.embeddedSearch.newTabPage.updateCustomLink; + +/** + * Embedded Search API methods defined in + * chrome/renderer/searchbox/searchbox_extension.cc: + * SearchBoxBindings::GetObjectTemplateBuilder() + */ +window.chrome.embeddedSearch.searchBox; +window.chrome.embeddedSearch.searchBox.isKeyCaptureEnabled; +window.chrome.embeddedSearch.searchBox.paste; +window.chrome.embeddedSearch.searchBox.startCapturingKeyStrokes; +window.chrome.embeddedSearch.searchBox.stopCapturingKeyStrokes; + + +/**************************** Translated Strings *****************************/ + +/** + * Translated strings defined in + * chrome/browser/search/local_ntp_source.cc: + * GetTranslatedStrings() + */ + +configData.translatedStrings.addLinkTitle; +configData.translatedStrings.addLinkTooltip; +configData.translatedStrings.attributionIntro; +configData.translatedStrings.audioError; +configData.translatedStrings.backLabel; +configData.translatedStrings.backgroundsUnavailable; +configData.translatedStrings.clickToViewDoodle; +configData.translatedStrings.connectionError; +configData.translatedStrings.connectionErrorNoPeriod; +configData.translatedStrings.copyLink; +configData.translatedStrings.customizeBackground; +configData.translatedStrings.customizeButtonLabel; +configData.translatedStrings.customizeThisPage; +configData.translatedStrings.dailyRefresh; +configData.translatedStrings.defaultWallpapers; +configData.translatedStrings.details; +configData.translatedStrings.editLinkTitle; +configData.translatedStrings.editLinkTooltip; +configData.translatedStrings.fakeboxMicrophoneTooltip; +configData.translatedStrings.invalidUrl; +configData.translatedStrings.languageError; +configData.translatedStrings.learnMore; +configData.translatedStrings.linkAddedMsg; +configData.translatedStrings.linkCancel; +configData.translatedStrings.linkCantCreate; +configData.translatedStrings.linkCantEdit; +configData.translatedStrings.linkCantRemove; +configData.translatedStrings.linkDone; +configData.translatedStrings.linkEditedMsg; +configData.translatedStrings.linkRemove; +configData.translatedStrings.linkRemovedMsg; +configData.translatedStrings.listening; +configData.translatedStrings.moreInfo; +configData.translatedStrings.mostVisitedTitle; +configData.translatedStrings.nameField; +configData.translatedStrings.networkError; +configData.translatedStrings.noTranslation; +configData.translatedStrings.noVoice; +configData.translatedStrings.otherError; +configData.translatedStrings.permissionError; +configData.translatedStrings.ready; +configData.translatedStrings.removeThumbnailTooltip; +configData.translatedStrings.restoreDefaultBackground; +configData.translatedStrings.restoreDefaultLinks; +configData.translatedStrings.restoreThumbnailsShort; +configData.translatedStrings.searchboxPlaceholder; +configData.translatedStrings.selectChromeWallpaper; +configData.translatedStrings.selectedLabel; +configData.translatedStrings.selectionCancel; +configData.translatedStrings.selectionDone; +configData.translatedStrings.shareClose; +configData.translatedStrings.shareDoodle; +configData.translatedStrings.shareFacebook; +configData.translatedStrings.shareLink; +configData.translatedStrings.shareMail; +configData.translatedStrings.shareTwitter; +configData.translatedStrings.thumbnailRemovedNotification; +configData.translatedStrings.title; +configData.translatedStrings.tryAgain; +configData.translatedStrings.undoThumbnailRemove; +configData.translatedStrings.uploadImage; +configData.translatedStrings.urlField; +configData.translatedStrings.waiting;
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js index e51029a..fdbf521 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.js +++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -53,8 +53,8 @@ * * @type {{ * numTitleLines: number, - * titleColor: string, - * titleColorAgainstDark: string, + * titleColor: Array<number>, + * titleColorAgainstDark: Array<number>, * }} */ var NTP_DESIGN = { @@ -359,7 +359,6 @@ * when considering darkness. Therefore, dark mode should only be checked if * this is the default NTP. Dark mode is considered a dark theme if enabled. * - * @param {ThemeBackgroundInfo|undefined} info Theme background information. * @return {boolean} Whether the theme is dark. * @private */ @@ -384,7 +383,7 @@ * is the case when dark mode is enabled and a background image (from a custom * background or user theme) is not set. * - * @param {ThemeBackgroundInfo|undefined} info Theme background information. + * @param {!Object} info Theme background information. * @return {boolean} Whether the chips should be dark. * @private */ @@ -588,9 +587,9 @@ * @private */ function setCustomThemeStyle(themeInfo) { - var textColor = null; - var textColorLight = null; - var mvxFilter = null; + var textColor = ''; + var textColorLight = ''; + var mvxFilter = ''; if (!themeInfo.usingDefaultTheme) { textColor = convertToRGBAColor(themeInfo.textColorRgba); textColorLight = convertToRGBAColor(themeInfo.textColorLightRgba); @@ -703,7 +702,8 @@ if (success) { showNotification(configData.translatedStrings.linkAddedMsg); } else { - showErrorNotification(configData.translatedStrings.linkCantCreate); + showErrorNotification( + configData.translatedStrings.linkCantCreate, null, null); } ntpApiHandle.logEvent(LOG_TYPE.NTP_CUSTOMIZE_SHORTCUT_DONE); } @@ -719,7 +719,8 @@ if (success) { showNotification(configData.translatedStrings.linkEditedMsg); } else { - showErrorNotification(configData.translatedStrings.linkCantEdit); + showErrorNotification( + configData.translatedStrings.linkCantEdit, null, null); } } @@ -734,7 +735,8 @@ if (success) { showNotification(configData.translatedStrings.linkRemovedMsg); } else { - showErrorNotification(configData.translatedStrings.linkCantRemove); + showErrorNotification( + configData.translatedStrings.linkCantRemove, null, null); } } @@ -788,10 +790,15 @@ * Animates the specified notification to float up. Automatically hides any * pre-existing notification and sets a delayed timer to hide the new * notification. - * @param {!Element} notification The notification element. - * @param {!Element} notificationContainer The notification container element. + * @param {?Element} notification The notification element. + * @param {?Element} notificationContainer The notification container element. */ function floatUpNotification(notification, notificationContainer) { + if (!notification || !notificationContainer) { + return; + } + + // Hide any pre-existing notification. if (delayedHideNotification) { // Hide the current notification if it's a different type (i.e. error vs // success). Otherwise, simply clear the notification timeout and reset it @@ -838,11 +845,15 @@ /** * Animates the pop-up notification to float down, and clears the timeout to * hide the notification. - * @param {!Element} notification The notification element. - * @param {!Element} notificationContainer The notification container element. + * @param {?Element} notification The notification element. + * @param {?Element} notificationContainer The notification container element. * @param {boolean} showPromo Do show the promo if present. */ function floatDownNotification(notification, notificationContainer, showPromo) { + if (!notification || !notificationContainer) { + return; + } + if (!notificationContainer.classList.contains(CLASSES.FLOAT_UP)) { return; } @@ -874,7 +885,7 @@ $(IDS.UNDO_LINK).blur(); $(IDS.RESTORE_ALL_LINK).blur(); if (notification.classList.contains(CLASSES.HAS_LINK)) { - notification.classlist.remove(CLASSES.HAS_LINK); + notification.classList.remove(CLASSES.HAS_LINK); $(IDS.ERROR_NOTIFICATION_LINK).blur(); } // Hide the notification @@ -968,8 +979,9 @@ * @return {boolean} True if the click occurred in an enabled fakebox. */ function isFakeboxClick(event) { - return $(IDS.FAKEBOX).contains(event.target) && - !$(IDS.FAKEBOX_MICROPHONE).contains(event.target); + return $(IDS.FAKEBOX).contains(/** @type HTMLElement */ (event.target)) && + !$(IDS.FAKEBOX_MICROPHONE) + .contains(/** @type HTMLElement */ (event.target)); } @@ -1079,7 +1091,7 @@ ssScript.async = false; document.body.appendChild(ssScript); ssScript.onload = function() { - injectSearchSuggestions(search_suggestions); + injectSearchSuggestions(searchSuggestions); }; } } @@ -1098,7 +1110,7 @@ // Hide notifications after fade out, so we can't focus on links via keyboard. $(IDS.NOTIFICATION).addEventListener('transitionend', (event) => { - if (event.properyName === 'opacity') { + if (event.propertyName === 'opacity') { hideNotification(); } });
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.js b/chrome/browser/resources/local_ntp/most_visited_single.js index fef9f4d4..06723921 100644 --- a/chrome/browser/resources/local_ntp/most_visited_single.js +++ b/chrome/browser/resources/local_ntp/most_visited_single.js
@@ -9,7 +9,7 @@ /** * Enum for key codes. - * @enum {int} + * @enum {number} * @const */ const KEYCODES = { @@ -156,7 +156,7 @@ * or 'chrome-search://local-ntp' for the local NTP. * @const {string} */ -var DOMAIN_ORIGIN = '{{ORIGIN}}'; +const DOMAIN_ORIGIN = '{{ORIGIN}}'; /** @@ -329,7 +329,7 @@ /** * Handler for the 'show' message from the host page. - * @param {object} info Data received in the message. + * @param {!Object} info Data received in the message. */ var showTiles = function(info) { logEvent(LOG_TYPE.NTP_ALL_TILES_RECEIVED); @@ -340,7 +340,7 @@ /** * Handler for the 'updateTheme' message from the host page. - * @param {object} info Data received in the message. + * @param {!Object} info Data received in the message. */ var updateTheme = function(info) { document.body.style.setProperty('--tile-title-color', info.tileTitleColor); @@ -361,7 +361,7 @@ * Handler for 'focusMenu' message from the host page. Focuses the edited tile's * menu or the add shortcut tile after closing the custom link edit dialog * without saving. - * @param {object} info Data received in the message. + * @param {!Object} info Data received in the message. */ var focusTileMenu = function(info) { let tile = document.querySelector(`a.md-tile[data-tid="${info.tid}"]`); @@ -402,6 +402,9 @@ 'title': queryArgs['addLink'], 'url': '', 'isAddButton': true, + 'dataGenerationTime': new Date(), + 'tileSource': -1, + 'tileTitleSource': -1 }; tiles.appendChild(renderMaterialDesignTile(data)); } @@ -441,7 +444,7 @@ // getComputedStyle causes the initial style (opacity 0) to be applied, so // that when we then set it to 1, that triggers the CSS transition. if (fadeIn) { - window.getComputedStyle(cur).opacity; + const style = window.getComputedStyle(cur).opacity; } cur.style.opacity = 1.0; @@ -475,7 +478,7 @@ * Handler for the 'show' message from the host page, called when it wants to * add a suggestion tile. * It's also used to fill up our tiles to |maxNumTiles| if necessary. - * @param {object} args Data for the tile to be rendered. + * @param {?MostVisitedData} args Data for the tile to be rendered. */ var addTile = function(args) { if (isFinite(args.rid)) { @@ -595,23 +598,28 @@ // Cancel the timeout if the user drags the mouse off the tile and // releases or if the mouse if released. - let dragend = document.addEventListener('dragend', () => { + let dragend = () => { window.clearTimeout(timeout); - }, {once: true}); - let mouseup = document.addEventListener('mouseup', () => { + }; + document.addEventListener('dragend', dragend, {once: true}); + + let mouseup = () => { if (event.button == 0 /* LEFT CLICK */) { window.clearTimeout(timeout); } - }, {once: true}); + }; + document.addEventListener('mouseup', mouseup, {once: true}); - // Wait for |REORDER_TIMEOUT_DELAY| before starting the reorder flow. - timeout = window.setTimeout(() => { + let timeoutFunc = (dragend_in, mouseup_in) => { if (!reordering) { startReorder(tile); } - document.removeEventListener('dragend', dragend); - document.removeEventListener('mouseup', mouseup); - }, REORDER_TIMEOUT_DELAY); + document.removeEventListener('dragend', dragend_in); + document.removeEventListener('mouseup', mouseup_in); + }; + // Wait for |REORDER_TIMEOUT_DELAY| before starting the reorder flow. + timeout = window.setTimeout( + timeoutFunc.bind(dragend, mouseup), REORDER_TIMEOUT_DELAY); } }); @@ -639,10 +647,11 @@ /** * Renders a MostVisited tile to the DOM. - * @param {object} data Object containing rid, url, title, favicon, thumbnail, - * and optionally isAddButton. isAddButton is true if you want to construct - * an add custom link button. data is null if you want to construct an - * empty tile. isAddButton can only be set if custom links is enabled. + * @param {?MostVisitedData} data Object containing rid, url, title, favicon, + * thumbnail, and optionally isAddButton. isAddButton is true if you want to + * construct an add custom link button. data is null if you want to + * construct an empty tile. isAddButton can only be set if custom links is + * enabled. */ var renderTile = function(data) { return renderMaterialDesignTile(data); @@ -651,9 +660,10 @@ /** * Renders a MostVisited tile with Material Design styles. - * @param {object} data Object containing rid, url, title, favicon, and - * optionally isAddButton. isAddButton is if you want to construct an add - * custom link button. data is null if you want to construct an empty tile. + * @param {?MostVisitedData} data Object containing rid, url, title, favicon, + * and optionally isAddButton. isAddButton is if you want to construct an + * add custom link button. data is null if you want to construct an empty + * tile. * @return {Element} */ function renderMaterialDesignTile(data) { @@ -684,7 +694,7 @@ mdTile.addEventListener('click', function(ev) { if (data.isAddButton) { - editCustomLink(); + editCustomLink(null); logEvent(LOG_TYPE.NTP_CUSTOMIZE_ADD_SHORTCUT_CLICKED); } else { logMostVisitedNavigation( @@ -820,7 +830,7 @@ // Don't allow the event to bubble out to the containing tile, as that would // trigger navigation to the tile URL. mdMenu.addEventListener('keydown', function(ev) { - event.stopPropagation(); + ev.stopPropagation(); }); utils.disableOutlineOnMouseClick(mdMenu);
diff --git a/chrome/browser/resources/local_ntp/most_visited_util.js b/chrome/browser/resources/local_ntp/most_visited_util.js index 00057a814..d568a79 100644 --- a/chrome/browser/resources/local_ntp/most_visited_util.js +++ b/chrome/browser/resources/local_ntp/most_visited_util.js
@@ -15,11 +15,11 @@ * The origin of this request. * @const {string} */ -var DOMAIN_ORIGIN = '{{ORIGIN}}'; +const MV_DOMAIN_ORIGIN = '{{ORIGIN}}'; /** * Parses query parameters from Location. - * @param {string} location The URL to generate the CSS url for. + * @param {!Location} location The URL to generate the CSS url for. * @return {Object} Dictionary containing name value pairs for URL. */ function parseQueryParams(location) { @@ -49,7 +49,7 @@ * @param {string} title The title for the link. * @param {string|undefined} text The text for the link or none. * @param {string|undefined} direction The text direction. - * @return {HTMLAnchorElement} A new link element. + * @return {!Element} A new link element. */ function createMostVisitedLink(params, href, title, text, direction) { var styles = getMostVisitedStyles(params, !!text); @@ -87,17 +87,18 @@ link.appendChild(spanWrap); } link.addEventListener('focus', function() { - window.parent.postMessage('linkFocused', DOMAIN_ORIGIN); + window.parent.postMessage('linkFocused', MV_DOMAIN_ORIGIN); }); link.addEventListener('blur', function() { - window.parent.postMessage('linkBlurred', DOMAIN_ORIGIN); + window.parent.postMessage('linkBlurred', MV_DOMAIN_ORIGIN); }); link.addEventListener('keydown', function(event) { if (event.keyCode == 46 /* DELETE */ || event.keyCode == 8 /* BACKSPACE */) { event.preventDefault(); - window.parent.postMessage('tileBlacklisted,' + params.pos, DOMAIN_ORIGIN); + window.parent.postMessage( + 'tileBlacklisted,' + params['pos'], MV_DOMAIN_ORIGIN); } else if ( event.keyCode == 13 /* ENTER */ || event.keyCode == 32 /* SPACE */) { // Event target is the <a> tag. Send a click event on it, which will @@ -197,7 +198,7 @@ /** - * @param {string} location A location containing URL parameters. + * @param {!Location} location A location containing URL parameters. * @param {function(Object, Object)} fill A function called with styles and * data to fill. */
diff --git a/chrome/browser/resources/local_ntp/utils.js b/chrome/browser/resources/local_ntp/utils.js index 90f489b..dd9dc02 100644 --- a/chrome/browser/resources/local_ntp/utils.js +++ b/chrome/browser/resources/local_ntp/utils.js
@@ -17,7 +17,7 @@ /** * Alias for document.getElementById. * @param {string} id The ID of the element to find. - * @return {HTMLElement} The found element or null if not found. + * @return {Element} The found element or null if not found. */ function $(id) { // eslint-disable-next-line no-restricted-properties
diff --git a/chrome/browser/resources/local_ntp/voice.js b/chrome/browser/resources/local_ntp/voice.js index 106dfe7..fe95c7df 100644 --- a/chrome/browser/resources/local_ntp/voice.js +++ b/chrome/browser/resources/local_ntp/voice.js
@@ -7,17 +7,6 @@ /** - * Alias for document.getElementById. - * @param {string} id The ID of the element to find. - * @return {HTMLElement} The found element or null if not found. - */ -function $(id) { - // eslint-disable-next-line no-restricted-properties - return document.getElementById(id); -} - - -/** * Get the preferred language for UI localization. Represents Chrome's UI * language, which might not coincide with the user's "preferred" language * in the Settings. For more details, see: @@ -307,7 +296,7 @@ /** * Log an event from Voice Search. - * @param {!number} eventType Event from |LOG_TYPE|. + * @param {number} eventType Event from |LOG_TYPE|. */ speech.logEvent = function(eventType) { window.chrome.embeddedSearch.newTabPage.logEvent(eventType); @@ -317,14 +306,18 @@ /** * Initialize the speech module as part of the local NTP. Adds event handlers * and shows the fakebox microphone icon. - * @param {!string} googleBaseUrl Base URL for sending queries to Search. + * @param {string} googleBaseUrl Base URL for sending queries to Search. * @param {!Object} translatedStrings Dictionary of localized string messages. - * @param {!HTMLElement} fakeboxMicrophoneElem Fakebox microphone icon element. + * @param {?Element} fakeboxMicrophoneElem Fakebox microphone icon element. * @param {!Object} searchboxApiHandle SearchBox API handle. */ speech.init = function( googleBaseUrl, translatedStrings, fakeboxMicrophoneElem, searchboxApiHandle) { + if (!fakeboxMicrophoneElem) { + throw new Error('Speech button element not found.'); + } + if (speech.currentState_ != speech.State_.UNINITIALIZED) { throw new Error( 'Trying to re-initialize speech when not in UNINITIALIZED state.'); @@ -666,7 +659,7 @@ /** * Determines, if the given KeyboardEvent |code| is a space or enter key. - * @param {!string} A KeyboardEvent's |code| property. + * @param {string} code A KeyboardEvent's |code| property. * @return True, iff the code represents a space or enter key. * @private */ @@ -684,7 +677,7 @@ /** * Determines if the given event's target id is for a button or navigation link. - * @param {!string} An event's target id. + * @param {string} id An event's target id. * @return True, iff the id is for a button or link. * @private */ @@ -706,7 +699,7 @@ * - <ESC> aborts voice input when the recognition interface is active. * - <ENTER> or <SPACE> interprets as a click if the target is a button or * navigation link, otherwise it submits the speech query if there is one - * @param {KeyboardEvent} event The keydown event. + * @param {!Event} event The keydown event. */ speech.onKeyDown = function(event) { if (speech.isUiDefinitelyHidden_()) { @@ -796,7 +789,7 @@ /** * Change the location of this tab to the new URL. Used for query submission. - * @param {!URL} The URL to navigate to. + * @param {!URL} url The URL to navigate to. * @private */ speech.navigateToUrl_ = function(url) { @@ -819,11 +812,11 @@ // before stopping speech. searchParams.append('q', speech.finalResult_); // Add a parameter to indicate that this request is a voice search. - searchParams.append('gs_ivs', 1); + searchParams.append('gs_ivs', '1'); // Build the query URL. const queryUrl = new URL('/search', speech.googleBaseUrl_); - queryUrl.search = searchParams; + queryUrl.search = searchParams.toString(); speech.logEvent(LOG_TYPE.ACTION_QUERY_SUBMITTED); speech.stop(); @@ -1110,8 +1103,8 @@ /** * Updates the text elements with new recognition results. - * @param {!string} interimText Low confidence speech recognition result text. - * @param {!string} opt_finalText High confidence speech recognition result + * @param {string} interimText Low confidence speech recognition result text. + * @param {string} opt_finalText High confidence speech recognition result * text, defaults to an empty string. */ text.updateTextArea = function(interimText, opt_finalText = '') { @@ -1690,7 +1683,7 @@ /** * Makes sure that a click anywhere closes the UI when it is active. - * @param {!MouseEvent} event The click event. + * @param {!Event} event The click event. * @private */ view.onWindowClick_ = function(event) {
diff --git a/chrome/browser/resources/md_extensions/keyboard_shortcuts.html b/chrome/browser/resources/md_extensions/keyboard_shortcuts.html index d8d6b472..ab08b83 100644 --- a/chrome/browser/resources/md_extensions/keyboard_shortcuts.html +++ b/chrome/browser/resources/md_extensions/keyboard_shortcuts.html
@@ -53,7 +53,7 @@ } .command-entry .md-select { - /* TODO(scottchen): line-height needs adjustment to fix large fonts. */ + /* TODO(johntlee): line-height needs adjustment to fix large fonts. */ line-height: 22px; margin-inline-start: var(--cr-section-padding); }
diff --git a/chrome/browser/resources/md_extensions/shared_style.html b/chrome/browser/resources/md_extensions/shared_style.html index 397c118..765e6c5 100644 --- a/chrome/browser/resources/md_extensions/shared_style.html +++ b/chrome/browser/resources/md_extensions/shared_style.html
@@ -77,8 +77,8 @@ margin-inline-end: var(--cr-section-padding); /* Makes the tappable area fill its parent. - * TODO(scottchen): This is an explicit reminder to override once - * .separator styling is extracted from settings. */ + * TODO(crbug.com/949697): This is an explicit reminder to override + * once .separator styling is extracted from settings. */ margin-inline-start: 0; }
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_section.js b/chrome/browser/resources/settings/autofill_page/autofill_section.js index b4d4d46..423ae7f 100644 --- a/chrome/browser/resources/settings/autofill_page/autofill_section.js +++ b/chrome/browser/resources/settings/autofill_page/autofill_section.js
@@ -161,8 +161,6 @@ onAddressMenuTap_: function(e) { const menuEvent = /** @type {!{model: !{item: !Object}}} */ (e); - /* TODO(scottchen): drop the [dataHost][dataHost] once this bug is fixed: - https://github.com/Polymer/polymer/issues/2574 */ // TODO(dpapad): The [dataHost][dataHost] workaround is only necessary for // Polymer 1. Remove once migration to Polymer 2 has completed. const item = Polymer.DomIf ? menuEvent.model.item :
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_browser_proxy.js b/chrome/browser/resources/settings/crostini_page/crostini_browser_proxy.js index 57f35c3..225da32 100644 --- a/chrome/browser/resources/settings/crostini_page/crostini_browser_proxy.js +++ b/chrome/browser/resources/settings/crostini_page/crostini_browser_proxy.js
@@ -45,8 +45,11 @@ */ setCrostiniUsbDeviceShared(guid, shared) {} - /** @param {string} path Path to stop sharing. */ - removeCrostiniSharedPath(path) {} + /** + * @param {string} vmName VM to stop sharing path with. + * @param {string} path Path to stop sharing. + */ + removeCrostiniSharedPath(vmName, path) {} /* Request chrome send a crostini-installer-status-changed event with the current installer status */ @@ -87,8 +90,8 @@ } /** @override */ - removeCrostiniSharedPath(path) { - chrome.send('removeCrostiniSharedPath', [path]); + removeCrostiniSharedPath(vmName, path) { + chrome.send('removeCrostiniSharedPath', [vmName, path]); } /** @override */
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_shared_paths.js b/chrome/browser/resources/settings/crostini_page/crostini_shared_paths.js index cc04e9ec..0072edd 100644 --- a/chrome/browser/resources/settings/crostini_page/crostini_shared_paths.js +++ b/chrome/browser/resources/settings/crostini_page/crostini_shared_paths.js
@@ -7,6 +7,15 @@ * 'crostini-shared-paths' is the settings shared paths subpage for Crostini. */ +(function() { + +/** + * The default crostini VM is named 'termina'. + * https://cs.chromium.org/chromium/src/chrome/browser/chromeos/crostini/crostini_util.h?q=kCrostiniDefaultVmName&dr=CSs + * @type {string} + */ +const DEFAULT_CROSTINI_VM = 'termina'; + Polymer({ is: 'settings-crostini-shared-paths', @@ -26,22 +35,27 @@ sharedPaths_: Array, }, - observers: - ['onCrostiniSharedPathsChanged_(prefs.crostini.shared_paths.value)'], + observers: [ + 'onCrostiniSharedPathsChanged_(prefs.guest_os.paths_shared_to_vms.value)' + ], /** - * @param {!Array<string>} paths + * @param {!Object<!Array<string>>} paths * @private */ onCrostiniSharedPathsChanged_: function(paths) { + const vmPaths = []; + for (const path in paths) { + const vms = paths[path]; + if (vms.includes(DEFAULT_CROSTINI_VM)) { + vmPaths.push(path); + } + } settings.CrostiniBrowserProxyImpl.getInstance() - .getCrostiniSharedPathsDisplayText(paths) + .getCrostiniSharedPathsDisplayText(vmPaths) .then(text => { - const sharedPaths = []; - for (let i = 0; i < paths.length; i++) { - sharedPaths.push({path: paths[i], pathDisplayText: text[i]}); - } - this.sharedPaths_ = sharedPaths; + this.sharedPaths_ = vmPaths.map( + (path, i) => ({path: path, pathDisplayText: text[i]})); }); }, @@ -51,6 +65,7 @@ */ onRemoveSharedPathTap_: function(event) { settings.CrostiniBrowserProxyImpl.getInstance().removeCrostiniSharedPath( - event.model.item.path); + DEFAULT_CROSTINI_VM, event.model.item.path); }, }); +})();
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html index ba44641..624536b 100644 --- a/chrome/browser/resources/settings/languages_page/languages_page.html +++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -23,6 +23,7 @@ <link rel="import" href="../controls/settings_toggle_button.html"> <link rel="import" href="../icons.html"> <link rel="import" href="../lifetime_browser_proxy.html"> +<link rel="import" href="../prefs/prefs_behavior.html"> <link rel="import" href="../route.html"> <link rel="import" href="../settings_page/settings_animated_pages.html"> <link rel="import" href="../settings_page/settings_subpage.html">
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.js b/chrome/browser/resources/settings/languages_page/languages_page.js index 289b434..63a360b 100644 --- a/chrome/browser/resources/settings/languages_page/languages_page.js +++ b/chrome/browser/resources/settings/languages_page/languages_page.js
@@ -26,6 +26,10 @@ Polymer({ is: 'settings-languages-page', + behaviors: [ + PrefsBehavior, + ], + properties: { /** * Preferences state. @@ -543,6 +547,17 @@ if (this.prefs == undefined) { return; } + + // <if expr="_google_chrome"> + // When spell check is disabled, automatically disable using the spelling + // service. This resets the spell check option to 'Use basic spell check' + // when spell check is turned off. This check is in an observer so that it + // can also correct any users who land on the Settings page and happen + // to have spelling service enabled but spell check disabled. + if (!this.getPref('browser.enable_spellchecking').value) { + this.setPrefValue('spellcheck.use_spelling_service', false); + } + // </if> }, /**
diff --git a/chrome/browser/resources/settings/people_page/people_page.js b/chrome/browser/resources/settings/people_page/people_page.js index 85affc8d..f91c493 100644 --- a/chrome/browser/resources/settings/people_page/people_page.js +++ b/chrome/browser/resources/settings/people_page/people_page.js
@@ -29,7 +29,7 @@ /** * This flag is used to conditionally show a set of new sign-in UIs to the * profiles that have been migrated to be consistent with the web sign-ins. - * TODO(scottchen): In the future when all profiles are completely migrated, + * TODO(tangltom): In the future when all profiles are completely migrated, * this should be removed, and UIs hidden behind it should become default. * @private */ @@ -44,7 +44,7 @@ /** * This flag is used to conditionally show a set of sync UIs to the * profiles that have been migrated to have a unified consent flow. - * TODO(scottchen): In the future when all profiles are completely migrated, + * TODO(tangltom): In the future when all profiles are completely migrated, * this should be removed, and UIs hidden behind it should become default. * @private */
diff --git a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html index 87ea931..6467115 100644 --- a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html +++ b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.html
@@ -19,7 +19,7 @@ <cr-input class="printer-name-input" autofocus id="printerName" value="{{activePrinter.printerName}}" - on-value-changed="onPrinterInfoChange_" + on-input="onPrinterInfoChange_" label="$i18n{printerName}" maxlength=64> </cr-input> @@ -28,7 +28,7 @@ <cr-input label="$i18n{printerAddress}" id="printerAddress" value="{{activePrinter.printerAddress}}" - on-value-changed="onPrinterInfoChange_" + on-input="onPrinterInfoChange_" disabled="[[!networkProtocolActive_]]" maxlength=128> </cr-input> @@ -72,7 +72,7 @@ <div class="settings-box two-line"> <cr-input id="printerQueue" label="$i18n{printerQueue}" value="{{activePrinter.printerQueue}}" - on-value-changed="onPrinterInfoChange_" + on-input="onPrinterInfoChange_" disabled="[[!networkProtocolActive_]]" maxlength=64> </cr-input> @@ -84,12 +84,14 @@ </div> <div class="settings-box two-line"> <cr-searchable-drop-down items="[[manufacturerList]]" + id="printerPPDManufacturer" label="$i18n{printerManufacturer}" value="{{activePrinter.ppdManufacturer}}"> </cr-searchable-drop-down> </div> <div class="settings-box two-line"> <cr-searchable-drop-down items="[[modelList]]" + id="printerPPDModel" label="$i18n{printerModel}" value="{{activePrinter.ppdModel}}"> </cr-searchable-drop-down> @@ -111,7 +113,8 @@ $i18n{cancel} </paper-button> <paper-button class="action-button" on-click="onSaveTap_" - disabled="[[!canSavePrinter_(activePrinter.*)]]"> + disabled="[[!canSavePrinter_(activePrinter.*, + printerInfoChanged_)]]"> $i18n{editPrinterButtonText} </paper-button> </div>
diff --git a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js index 643c84b..83f5ab6 100644 --- a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js +++ b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js
@@ -38,6 +38,18 @@ /** + * Tracks whether the dialog is fully initialized. This is required because + * the dialog isn't fully initialized until Model and Manufacturer are set. + * Allows us to ignore changes made to these fields until initialization is + * complete. + * @private + */ + arePrinterFieldsInitialized_: { + type: Boolean, + value: false, + }, + + /** * If the printer info has changed since loading this dialog. This will * only track the freeform input fields, since the other fields contain * input selected from dropdown menus. @@ -78,6 +90,7 @@ observers: [ 'printerPathChanged_(activePrinter.*)', 'selectedEditManufacturerChanged_(activePrinter.ppdManufacturer)', + 'onModelChanged_(activePrinter.ppdModel)', ], /** @override */ @@ -110,6 +123,7 @@ */ onProtocolChange_: function(event) { this.set('activePrinter.printerProtocol', event.target.value); + this.onPrinterInfoChange_(); }, /** @private */ @@ -125,8 +139,8 @@ /** @private */ onSaveTap_: function() { if (this.needsReconfigured_) { - settings.CupsPrintersBrowserProxyImpl.getInstance().addCupsPrinter( - this.activePrinter); + settings.CupsPrintersBrowserProxyImpl.getInstance() + .reconfigureCupsPrinter(this.activePrinter); } else { settings.CupsPrintersBrowserProxyImpl.getInstance().updateCupsPrinter( this.activePrinter.printerId, this.activePrinter.printerName); @@ -190,7 +204,7 @@ * @private */ canSavePrinter_: function() { - return !this.printerInfoChanged_ || + return this.printerInfoChanged_ && (settings.printing.isNameAndAddressValid(this.activePrinter) && settings.printing.isPPDInfoValid( this.activePrinter.ppdManufacturer, this.activePrinter.ppdModel, @@ -213,6 +227,16 @@ } }, + /** + * Sets printerInfoChanged_ to true to show that the model has changed. + * @private + */ + onModelChanged_: function() { + if (this.arePrinterFieldsInitialized_) { + this.printerInfoChanged_ = true; + } + }, + /** @private */ onBrowseFile_: function() { settings.CupsPrintersBrowserProxyImpl.getInstance() @@ -243,6 +267,8 @@ modelListChanged_: function(modelsInfo) { if (modelsInfo.success) { this.modelList = modelsInfo.models; + // ModelListChanged_ is the final step of initializing activePrinter. + this.arePrinterFieldsInitialized_ = true; } }, @@ -253,6 +279,10 @@ printerPPDPathChanged_: function(path) { this.set('activePrinter.printerPPDPath', path); this.invalidPPD_ = !path; + if (!this.invalidPPD_) { + // A new valid PPD file should be treated as a saveable change. + this.onPrinterInfoChange_(); + } this.userPPD_ = settings.printing.getBaseName(path); }, });
diff --git a/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js b/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js index 61eaa1c7..d083e82 100644 --- a/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js +++ b/chrome/browser/resources/settings/printing_page/cups_printers_browser_proxy.js
@@ -139,6 +139,11 @@ */ addCupsPrinter(newPrinter) {} + /** + * @param {!CupsPrinterInfo} printer + */ + reconfigureCupsPrinter(printer) {} + startDiscoveringPrinters() {} stopDiscoveringPrinters() {} @@ -202,6 +207,11 @@ } /** @override */ + reconfigureCupsPrinter(printer) { + chrome.send('reconfigureCupsPrinter', [printer]); + } + + /** @override */ getCupsPrinterPPDPath() { return cr.sendWithPromise('selectPPDFile'); }
diff --git a/chrome/browser/resources/settings/privacy_page/BUILD.gn b/chrome/browser/resources/settings/privacy_page/BUILD.gn index bfb43ba..3077a57 100644 --- a/chrome/browser/resources/settings/privacy_page/BUILD.gn +++ b/chrome/browser/resources/settings/privacy_page/BUILD.gn
@@ -22,6 +22,7 @@ "..:route", "../controls:settings_toggle_button", "../people_page:sync_browser_proxy", + "../prefs:prefs_behavior", "//ui/webui/resources/js:web_ui_listener_behavior", ] externs_list = [ "$externs_path/settings_private.js" ]
diff --git a/chrome/browser/resources/settings/privacy_page/personalization_options.html b/chrome/browser/resources/settings/privacy_page/personalization_options.html index 13d16bb..7efe994e 100644 --- a/chrome/browser/resources/settings/privacy_page/personalization_options.html +++ b/chrome/browser/resources/settings/privacy_page/personalization_options.html
@@ -6,6 +6,7 @@ <link rel="import" href="../controls/settings_toggle_button.html"> <link rel="import" href="../lifetime_browser_proxy.html"> <link rel="import" href="../people_page/sync_browser_proxy.html"> +<link rel="import" href="../prefs/prefs_behavior.html"> <link rel="import" href="../route.html"> <link rel="import" href="../settings_shared_css.html"> <link rel="import" href="privacy_page_browser_proxy.html"> @@ -78,6 +79,7 @@ <if expr="_google_chrome"> <settings-toggle-button id="spellCheckControl" pref="{{prefs.spellcheck.use_spelling_service}}" + on-settings-boolean-control-change="onUseSpellingServiceToggle_" label="$i18n{spellingPref}" sub-label="$i18n{spellingDescription}" hidden="[[!showSpellCheckControl_(prefs.spellcheck.dictionaries)]]">
diff --git a/chrome/browser/resources/settings/privacy_page/personalization_options.js b/chrome/browser/resources/settings/privacy_page/personalization_options.js index c6ffda1..f3a7ad0 100644 --- a/chrome/browser/resources/settings/privacy_page/personalization_options.js +++ b/chrome/browser/resources/settings/privacy_page/personalization_options.js
@@ -13,6 +13,7 @@ is: 'settings-personalization-options', behaviors: [ + PrefsBehavior, WebUIListenerBehavior, ], @@ -107,6 +108,20 @@ }, // </if> + // <if expr="_google_chrome"> + /** + * @param {!Event} event + * @private + */ + onUseSpellingServiceToggle_: function(event) { + // If turning on using the spelling service, automatically turn on + // spellcheck so that the spelling service can run. + if (event.target.checked) { + this.setPrefValue('browser.enable_spellchecking', true); + } + }, + // </if> + /** * @return {boolean} * @private
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.js b/chrome/browser/resources/settings/privacy_page/privacy_page.js index e89e377..9fde0dc 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.js +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.js
@@ -186,7 +186,7 @@ /** * This flag is used to conditionally show a set of sync UIs to the * profiles that have been migrated to have a unified consent flow. - * TODO(scottchen): In the future when all profiles are completely migrated, + * TODO(tangltom): In the future when all profiles are completely migrated, * this should be removed, and UIs hidden behind it should become default. * @private */
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js index 90a2745..5507464 100644 --- a/chrome/browser/resources/settings/route.js +++ b/chrome/browser/resources/settings/route.js
@@ -687,11 +687,11 @@ new URLSearchParams(window.location.search), true); }); - // TODO(scottchen): Change to 'get routes() {}' in export when we fix a bug in + // TODO(dpapad): Change to 'get routes() {}' in export when we fix a bug in // ChromePass that limits the syntax of what can be returned from cr.define(). const routes = routerInstance.getRoutes(); - // TODO(scottchen): Stop exposing all those methods directly on settings.*, + // TODO(dpapad): Stop exposing all those methods directly on settings.*, // and instead update all clients to use the singleton instance directly const getCurrentRoute = routerInstance.getCurrentRoute.bind(routerInstance); const getRouteForPath = routerInstance.getRouteForPath.bind(routerInstance);
diff --git a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js index a1e3687f..1611ba92 100644 --- a/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js +++ b/chrome/browser/resources/signin/sync_confirmation/sync_confirmation.js
@@ -93,7 +93,7 @@ } } - // TODO(scottchen): clearFocus and setUserImageURL are called directly by the + // TODO(tangltom): clearFocus and setUserImageURL are called directly by the // C++ handler. C++ handlers should not be calling JS functions by name // anymore. They should be firing events with FireWebuiListener and have the // page itself decide whether to listen or not listen to the event.
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn index 9617283aa..b7a963c 100644 --- a/chrome/browser/safe_browsing/BUILD.gn +++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -312,7 +312,6 @@ "//chrome/common/safe_browsing:proto", "//components/safe_browsing/db:database_manager", "//components/safe_browsing/db:test_database_manager", - "//components/safe_browsing/db:v4_feature_list", "//components/safe_browsing/db:v4_protocol_manager_util", "//content/public/browser:browser", ]
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_service_browsertest.cc b/chrome/browser/safe_browsing/download_protection/download_protection_service_browsertest.cc deleted file mode 100644 index 97708b2..0000000 --- a/chrome/browser/safe_browsing/download_protection/download_protection_service_browsertest.cc +++ /dev/null
@@ -1,121 +0,0 @@ -// Copyright (c) 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/files/file_path.h" -#include "base/path_service.h" -#include "base/run_loop.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" -#include "components/safe_browsing/proto/csd.pb.h" -#include "components/safe_browsing/web_ui/safe_browsing_ui.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/download_manager.h" -#include "content/public/browser/site_instance.h" -#include "content/public/test/browser_test.h" -#include "crypto/sha2.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/window_open_disposition.h" - -namespace safe_browsing { - -class DownloadProtectionServiceBrowserTest : public InProcessBrowserTest { - protected: - base::FilePath GetTestDataDirectory() { - base::FilePath test_file_directory; - base::PathService::Get(chrome::DIR_TEST_DATA, &test_file_directory); - return test_file_directory; - } - - void DownloadAndWait(GURL url) { - content::DownloadManager* download_manager = - content::BrowserContext::GetDownloadManager(browser()->profile()); - - // This call will block until the navigation completes, but will not wait - // for the download to finish. - ui_test_utils::NavigateToURLWithDisposition( - browser(), url, WindowOpenDisposition::CURRENT_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - - // Waits for the download to complete. - while (download_manager->InProgressCount() > 0) { - base::RunLoop run_loop; - run_loop.RunUntilIdle(); - } - } - - // The hash of 10 A's, followed by a newline. Was generated as follows: - // echo "AAAAAAAAAA" > a.zip - // sha256sum a.zip - static const uint8_t kAZipDigest[]; - - // The hash of 9 B's, followed by a newline. Was generated as follows: - // echo "BBBBBBBBB" > a.zip - // sha256sum a.zip - static const uint8_t kBZipDigest[]; -}; - -const uint8_t DownloadProtectionServiceBrowserTest::kAZipDigest[] = { - 0x70, 0x5d, 0x29, 0x0c, 0x12, 0x89, 0x59, 0x01, 0xf8, 0x09, 0xf6, - 0xc2, 0xfe, 0x77, 0x2a, 0x94, 0xdb, 0x51, 0x81, 0xd7, 0x26, 0x46, - 0x4d, 0x84, 0x06, 0x82, 0x10, 0x6f, 0x4a, 0x93, 0x4b, 0x87}; - -const uint8_t DownloadProtectionServiceBrowserTest::kBZipDigest[] = { - 0x94, 0x1e, 0x17, 0x3f, 0x62, 0xbc, 0x04, 0x50, 0x6f, 0xeb, 0xb5, - 0xe2, 0x8c, 0x38, 0x6c, 0xb2, 0x11, 0x91, 0xf3, 0x77, 0xa7, 0x2c, - 0x11, 0x92, 0xe0, 0x25, 0xb0, 0xe5, 0xc7, 0x70, 0x3b, 0x23}; - -IN_PROC_BROWSER_TEST_F(DownloadProtectionServiceBrowserTest, VerifyZipHash) { - embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory()); - ASSERT_TRUE(embedded_test_server()->Start()); - - WebUIInfoSingleton::GetInstance()->AddListenerForTesting(); - - GURL url = embedded_test_server()->GetURL( - "/safe_browsing/download_protection/zipfile_two_archives.zip"); - DownloadAndWait(url); - - const std::vector<std::unique_ptr<ClientDownloadRequest>>& requests = - WebUIInfoSingleton::GetInstance()->client_download_requests_sent(); - - ASSERT_EQ(1u, requests.size()); - ASSERT_EQ(2, requests[0]->archived_binary_size()); - - EXPECT_EQ("a.zip", requests[0]->archived_binary(0).file_basename()); - EXPECT_EQ(std::string(kAZipDigest, kAZipDigest + crypto::kSHA256Length), - requests[0]->archived_binary(0).digests().sha256()); - - EXPECT_EQ("b.zip", requests[0]->archived_binary(1).file_basename()); - EXPECT_EQ(std::string(kBZipDigest, kBZipDigest + crypto::kSHA256Length), - requests[0]->archived_binary(1).digests().sha256()); -} - -IN_PROC_BROWSER_TEST_F(DownloadProtectionServiceBrowserTest, VerifyRarHash) { - embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory()); - ASSERT_TRUE(embedded_test_server()->Start()); - - WebUIInfoSingleton::GetInstance()->AddListenerForTesting(); - - GURL url = - embedded_test_server()->GetURL("/safe_browsing/rar/has_two_archives.rar"); - DownloadAndWait(url); - - const std::vector<std::unique_ptr<ClientDownloadRequest>>& requests = - WebUIInfoSingleton::GetInstance()->client_download_requests_sent(); - - ASSERT_EQ(1u, requests.size()); - ASSERT_EQ(2, requests[0]->archived_binary_size()); - - EXPECT_EQ("a.zip", requests[0]->archived_binary(0).file_basename()); - EXPECT_EQ(std::string(kAZipDigest, kAZipDigest + crypto::kSHA256Length), - requests[0]->archived_binary(0).digests().sha256()); - - EXPECT_EQ("b.zip", requests[0]->archived_binary(1).file_basename()); - EXPECT_EQ(std::string(kBZipDigest, kBZipDigest + crypto::kSHA256Length), - requests[0]->archived_binary(1).digests().sha256()); -} - -} // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc index 00421a2..d42033c9 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -69,7 +69,6 @@ #include "components/safe_browsing/db/test_database_manager.h" #include "components/safe_browsing/db/util.h" #include "components/safe_browsing/db/v4_database.h" -#include "components/safe_browsing/db/v4_feature_list.h" #include "components/safe_browsing/db/v4_get_hash_protocol_manager.h" #include "components/safe_browsing/db/v4_protocol_manager_util.h" #include "components/safe_browsing/db/v4_test_util.h"
diff --git a/chrome/browser/safe_browsing/test_safe_browsing_service.cc b/chrome/browser/safe_browsing/test_safe_browsing_service.cc index 3eb4ee65..51daa003 100644 --- a/chrome/browser/safe_browsing/test_safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/test_safe_browsing_service.cc
@@ -10,7 +10,6 @@ #include "chrome/browser/safe_browsing/ui_manager.h" #include "components/safe_browsing/db/database_manager.h" #include "components/safe_browsing/db/test_database_manager.h" -#include "components/safe_browsing/db/v4_feature_list.h" namespace safe_browsing {
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc index 028e4d2..0bb1d77 100644 --- a/chrome/browser/search/local_ntp_source.cc +++ b/chrome/browser/search/local_ntp_source.cc
@@ -222,6 +222,8 @@ IDS_NTP_CUSTOM_BG_CUSTOMIZE_NTP_LABEL); AddString(translated_strings.get(), "backLabel", IDS_NTP_CUSTOM_BG_BACK_LABEL); + AddString(translated_strings.get(), "selectedLabel", + IDS_NTP_CUSTOM_BG_IMAGE_SELECTED); // Custom Links AddString(translated_strings.get(), "addLinkTitle", @@ -855,7 +857,7 @@ // check must be changed. if (one_google_bar_service_->language_code() != kEnUSLanguageCode) { std::string no_suggestions = - "var search_suggestions = {suggestionsHtml: ''}"; + "var searchSuggestions = {suggestionsHtml: ''}"; callback.Run(base::RefCountedString::TakeString(&no_suggestions)); return; } @@ -1051,7 +1053,7 @@ return; std::string js_errors = - "var coll_errors = " + + "var collErrors = " + GetErrorDict(ntp_background_service_->collection_error_info()); scoped_refptr<base::RefCountedString> result; @@ -1089,7 +1091,7 @@ return; std::string js_errors = - "var coll_img_errors = " + + "var collImgErrors = " + GetErrorDict(ntp_background_service_->collection_images_error_info()); scoped_refptr<base::RefCountedString> result; @@ -1097,7 +1099,7 @@ base::JSONWriter::Write(ConvertCollectionImageToDict( ntp_background_service_->collection_images()), &js); - js = "var coll_img = " + js + "; " + js_errors; + js = "var collImg = " + js + "; " + js_errors; result = base::RefCountedString::TakeString(&js); base::TimeTicks now = base::TimeTicks::Now(); @@ -1204,7 +1206,7 @@ scoped_refptr<base::RefCountedString> result; std::string js; base::JSONWriter::Write(*ConvertSearchSuggestDataToDict(data), &js); - js = "var search_suggestions = " + js + ";"; + js = "var searchSuggestions = " + js + ";"; result = base::RefCountedString::TakeString(&js); callback.Run(result); }
diff --git a/chrome/browser/sync/profile_sync_service_factory_unittest.cc b/chrome/browser/sync/profile_sync_service_factory_unittest.cc index 3bbf083..d5198ac 100644 --- a/chrome/browser/sync/profile_sync_service_factory_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_factory_unittest.cc
@@ -42,7 +42,7 @@ // Returns the collection of default datatypes. std::vector<syncer::ModelType> DefaultDatatypes() { - static_assert(44 == syncer::MODEL_TYPE_COUNT, + static_assert(44 == syncer::ModelType::NUM_ENTRIES, "When adding a new type, you probably want to add it here as " "well (assuming it is already enabled).");
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 3f9150d..dcc5061 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1762,6 +1762,8 @@ "webui/settings/chromeos/internet_handler.h", "webui/settings/chromeos/multidevice_handler.cc", "webui/settings/chromeos/multidevice_handler.h", + "webui/settings/chromeos/os_settings_ui.cc", + "webui/settings/chromeos/os_settings_ui.h", "webui/settings/tts_handler.cc", "webui/settings/tts_handler.h", "webui/signin/inline_login_handler_chromeos.cc",
diff --git a/chrome/browser/ui/OWNERS b/chrome/browser/ui/OWNERS index d7e7476..744ff0a 100644 --- a/chrome/browser/ui/OWNERS +++ b/chrome/browser/ui/OWNERS
@@ -21,4 +21,6 @@ per-file avatar_*=file://components/signin/OWNERS per-file signin_*=file://components/signin/OWNERS +per-file settings_window_manager_chromeos*=file://chrome/browser/ui/ash/OWNERS + # COMPONENT: UI>Browser
diff --git a/chrome/browser/ui/settings_window_manager_chromeos.cc b/chrome/browser/ui/settings_window_manager_chromeos.cc index d24a0f3..b4d67bb 100644 --- a/chrome/browser/ui/settings_window_manager_chromeos.cc +++ b/chrome/browser/ui/settings_window_manager_chromeos.cc
@@ -24,7 +24,6 @@ #include "ui/aura/client/aura_constants.h" #include "ui/base/ui_base_features.h" #include "url/gurl.h" -#include "url/url_constants.h" namespace chrome { @@ -112,8 +111,7 @@ void SettingsWindowManager::ShowOSSettings(Profile* profile) { if (base::FeatureList::IsEnabled(chromeos::features::kSplitSettings)) { - // TODO(jamescook): Add an "os-settings" URL and host. - ShowChromePageForProfile(profile, GURL(url::kAboutBlankURL)); + ShowChromePageForProfile(profile, GURL(kChromeUIOSSettingsURL)); return; } ShowChromePageForProfile(profile, GURL(kChromeUISettingsURL));
diff --git a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc index 7f0e4c6..36a14cf 100644 --- a/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc +++ b/chrome/browser/ui/views/ime_driver/input_method_bridge_chromeos.cc
@@ -64,7 +64,8 @@ ui::KeyEvent* key_event = event->AsKeyEvent(); if (IsActiveInputContextHandler(input_method_chromeos_.get()) && !key_event->is_char()) { - input_method_chromeos_->DispatchKeyEvent(key_event, std::move(callback)); + input_method_chromeos_->DispatchKeyEventAsync(key_event, + std::move(callback)); } else { const bool handled = false; std::move(callback).Run(handled);
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_view.cc b/chrome/browser/ui/views/media_router/cast_dialog_view.cc index 0c372bf..9a0b58f 100644 --- a/chrome/browser/ui/views/media_router/cast_dialog_view.cc +++ b/chrome/browser/ui/views/media_router/cast_dialog_view.cc
@@ -65,6 +65,16 @@ } // static +void CastDialogView::ShowDialogCenteredForBrowserWindow( + CastDialogController* controller, + Browser* browser, + const base::Time& start_time) { + ShowDialog(BrowserView::GetBrowserViewForBrowser(browser)->top_container(), + views::BubbleBorder::TOP_CENTER, controller, browser->profile(), + start_time); +} + +// static void CastDialogView::ShowDialogCentered(const gfx::Rect& bounds, CastDialogController* controller, Profile* profile,
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_view.h b/chrome/browser/ui/views/media_router/cast_dialog_view.h index 270731a..61fa985 100644 --- a/chrome/browser/ui/views/media_router/cast_dialog_view.h +++ b/chrome/browser/ui/views/media_router/cast_dialog_view.h
@@ -53,6 +53,13 @@ Browser* browser, const base::Time& start_time); + // Shows the singleton dialog anchored to the top-center of the browser + // window. + static void ShowDialogCenteredForBrowserWindow( + CastDialogController* controller, + Browser* browser, + const base::Time& start_time); + // Shows the singleton dialog anchored to the bottom of |bounds|, horizontally // centered. static void ShowDialogCentered(const gfx::Rect& bounds,
diff --git a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc index 63ba6184..9a9dda47 100644 --- a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc +++ b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
@@ -72,10 +72,8 @@ CastDialogView::ShowDialogWithToolbarAction(ui_.get(), browser, dialog_creation_time); } else { - const gfx::Rect& anchor_bounds = - browser_view->top_container()->GetBoundsInScreen(); - CastDialogView::ShowDialogCentered(anchor_bounds, ui_.get(), profile, - dialog_creation_time); + CastDialogView::ShowDialogCenteredForBrowserWindow(ui_.get(), browser, + dialog_creation_time); } } else { gfx::Rect anchor_bounds = initiator()->GetContainerBounds();
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc index 84edbb9..d44abc6 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc +++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
@@ -267,6 +267,10 @@ } } +bool TabHoverCardBubbleView::IsFadingOut() const { + return fade_animation_delegate_->IsFadingOut(); +} + int TabHoverCardBubbleView::GetDialogButtons() const { return ui::DIALOG_BUTTON_NONE; }
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h index ddd14efa86..f65412ca 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h +++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.h
@@ -37,6 +37,8 @@ void FadeOutToHide(); + bool IsFadingOut() const; + // BubbleDialogDelegateView: int GetDialogButtons() const override;
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 607215a..9580e58 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -2715,7 +2715,7 @@ return false; return hover_card_ && hover_card_->GetWidget()->IsVisible() && - hover_card_->GetAnchorView() == tab; + !hover_card_->IsFadingOut() && hover_card_->GetAnchorView() == tab; } void TabStrip::ButtonPressed(views::Button* sender, const ui::Event& event) {
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index 2327bcf..56cb558 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -67,6 +67,7 @@ #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" +#include "chrome/common/webui_url_constants.h" #include "components/dom_distiller/core/dom_distiller_constants.h" #include "components/dom_distiller/core/dom_distiller_features.h" #include "components/dom_distiller/core/dom_distiller_service.h" @@ -167,6 +168,7 @@ #include "chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h" #include "chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.h" #include "chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_ui.h" +#include "chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h" #include "chrome/browser/ui/webui/signin/inline_login_ui.h" #include "chromeos/components/multidevice/debug_webui/proximity_auth_ui.h" #include "chromeos/components/multidevice/debug_webui/url_constants.h" @@ -513,6 +515,8 @@ return &NewWebUI<chromeos::NetworkUI>; if (url.host_piece() == chrome::kChromeUIOobeHost) return &NewWebUI<chromeos::OobeUI>; + if (url.host_piece() == chrome::kChromeUIOSSettingsHost) + return &NewWebUI<chromeos::settings::OSSettingsUI>; if (url.host_piece() == chrome::kChromeUIPowerHost) return &NewWebUI<chromeos::PowerUI>; if (url.host_piece() == chromeos::multidevice::kChromeUIProximityAuthHost)
diff --git a/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc b/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc index 4277488..22fee22 100644 --- a/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc +++ b/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc
@@ -111,9 +111,9 @@ weak_ptr_factory_(this) {} KioskAppsHandler::~KioskAppsHandler() { - // TODO(scottchen): This is needed because OnJavascriptDisallowed only called + // TODO(tommycli): This is needed because OnJavascriptDisallowed only called // with refresh or off-page navigation, otherwise DCHECK triggered when - // exiting. Ask tommycli for more information. + // exiting. kiosk_app_manager_->RemoveObserver(this); }
diff --git a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc index 99048ab..7559e03 100644 --- a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
@@ -120,12 +120,14 @@ void CrostiniHandler::HandleRemoveCrostiniSharedPath( const base::ListValue* args) { - CHECK_EQ(1U, args->GetSize()); + CHECK_EQ(2U, args->GetSize()); + std::string vm_name; + CHECK(args->GetString(0, &vm_name)); std::string path; - CHECK(args->GetString(0, &path)); + CHECK(args->GetString(1, &path)); crostini::CrostiniSharePath::GetForProfile(profile_)->UnsharePath( - crostini::kCrostiniDefaultVmName, base::FilePath(path), + vm_name, base::FilePath(path), /*unpersist=*/true, base::BindOnce( [](const std::string& path, bool result, std::string failure_reason) {
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc index decd9f8..8eeeea9 100644 --- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -309,6 +309,10 @@ base::BindRepeating(&CupsPrintersHandler::HandleAddCupsPrinter, base::Unretained(this))); web_ui()->RegisterMessageCallback( + "reconfigureCupsPrinter", + base::BindRepeating(&CupsPrintersHandler::HandleReconfigureCupsPrinter, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( "getPrinterInfo", base::BindRepeating(&CupsPrintersHandler::HandleGetPrinterInfo, base::Unretained(this))); @@ -387,7 +391,7 @@ printer.set_display_name(printer_name); if (!profile_->GetPrefs()->GetBoolean(prefs::kUserNativePrintersAllowed)) { - PRINTER_LOG(DEBUG) << "HandleAddCupsPrinter() called when " + PRINTER_LOG(DEBUG) << "HandleUpdateCupsPrinter() called when " "kUserNativePrintersAllowed is set to false"; // Used to log UMA metrics. OnAddedOrEditedPrinterCommon( @@ -586,7 +590,17 @@ void CupsPrintersHandler::HandleAddCupsPrinter(const base::ListValue* args) { AllowJavascript(); + AddOrReconfigurePrinter(args, false /* is_printer_edit */); +} +void CupsPrintersHandler::HandleReconfigureCupsPrinter( + const base::ListValue* args) { + AllowJavascript(); + AddOrReconfigurePrinter(args, true /* is_printer_edit */); +} + +void CupsPrintersHandler::AddOrReconfigurePrinter(const base::ListValue* args, + bool is_printer_edit) { const base::DictionaryValue* printer_dict = nullptr; CHECK(args->GetDictionary(0, &printer_dict)); @@ -598,7 +612,7 @@ } if (!profile_->GetPrefs()->GetBoolean(prefs::kUserNativePrintersAllowed)) { - PRINTER_LOG(DEBUG) << "HandleAddCupsPrinter() called when " + PRINTER_LOG(DEBUG) << "AddOrReconfigurePrinter() called when " "kUserNativePrintersAllowed is set to false"; // Used to log UMA metrics. OnAddedOrEditedPrinterCommon( @@ -616,18 +630,22 @@ return; } - // If the provided printer already exists, grab the existing printer object - // and check that we are not making any changes that will make the - // printerexisting_printer unusable. - const bool is_existing_printer = !printer->id().empty(); - if (is_existing_printer) { - std::unique_ptr<Printer> existing_printer = - printers_manager_->GetPrinter(printer->id()); - if (existing_printer) { - if (!IsValidUriChange(*existing_printer, *printer)) { - OnAddOrEditPrinterError(PrinterSetupResult::kInvalidPrinterUpdate); - return; - } + // Grab the existing printer object and check that we are not making any + // changes that will make |existing_printer_object| unusable. + if (printer->id().empty()) { + // If the printer object has not already been created, error out since this + // is not a valid case. + PRINTER_LOG(ERROR) << "Failed to parse printer ID"; + OnAddOrEditPrinterError(PrinterSetupResult::kFatalError); + return; + } + + std::unique_ptr<Printer> existing_printer_object = + printers_manager_->GetPrinter(printer->id()); + if (existing_printer_object) { + if (!IsValidUriChange(*existing_printer_object, *printer)) { + OnAddOrEditPrinterError(PrinterSetupResult::kInvalidPrinterUpdate); + return; } } @@ -691,9 +709,9 @@ } printer_configurer_->SetUpPrinter( - *printer, base::BindOnce( - &CupsPrintersHandler::OnAddedOrEditedSpecifiedPrinter, - weak_factory_.GetWeakPtr(), *printer, is_existing_printer)); + *printer, + base::BindOnce(&CupsPrintersHandler::OnAddedOrEditedSpecifiedPrinter, + weak_factory_.GetWeakPtr(), *printer, is_printer_edit)); } void CupsPrintersHandler::OnAddedOrEditedPrinterCommon(
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h index d6a1a8c..3e4d7d2 100644 --- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
@@ -103,10 +103,15 @@ void HandleAddCupsPrinter(const base::ListValue* args); + void HandleReconfigureCupsPrinter(const base::ListValue* args); + + void AddOrReconfigurePrinter(const base::ListValue* args, + bool is_printer_edit); + // Handles the result of adding a printer which the user specified the // location of (i.e. a printer that was not 'discovered' automatically). void OnAddedOrEditedSpecifiedPrinter(const Printer& printer, - bool is_existing_printer, + bool is_printer_edit, PrinterSetupResult result); // Handles the result of failure to add a printer. |result_code| is used to
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc new file mode 100644 index 0000000..0375c27 --- /dev/null +++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
@@ -0,0 +1,34 @@ +// 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 "chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/webui_url_constants.h" +#include "chrome/grit/browser_resources.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" + +namespace chromeos { +namespace settings { + +OSSettingsUI::OSSettingsUI(content::WebUI* web_ui) + : content::WebUIController(web_ui) { + Profile* profile = Profile::FromWebUI(web_ui); + content::WebUIDataSource* html_source = + content::WebUIDataSource::Create(chrome::kChromeUIOSSettingsHost); + + // TODO(jamescook): Factor out page handlers from MdSettingsUI and initialize + // them both there and here. + + html_source->UseGzip(); + html_source->SetDefaultResource(IDR_OS_SETTINGS_HTML); + + content::WebUIDataSource::Add(profile, html_source); +} + +OSSettingsUI::~OSSettingsUI() = default; + +} // namespace settings +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h new file mode 100644 index 0000000..6f5fdbd --- /dev/null +++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h
@@ -0,0 +1,27 @@ +// 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 CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_UI_H_ + +#include "base/macros.h" +#include "content/public/browser/web_ui_controller.h" + +namespace chromeos { +namespace settings { + +// The WebUI handler for chrome://os-settings. +class OSSettingsUI : public content::WebUIController { + public: + explicit OSSettingsUI(content::WebUI* web_ui); + ~OSSettingsUI() override; + + private: + DISALLOW_COPY_AND_ASSIGN(OSSettingsUI); +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_UI_H_
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.h b/chrome/browser/ui/webui/settings/md_settings_ui.h index f9182a0..3aa5270 100644 --- a/chrome/browser/ui/webui/settings/md_settings_ui.h +++ b/chrome/browser/ui/webui/settings/md_settings_ui.h
@@ -5,8 +5,6 @@ #ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_MD_SETTINGS_UI_H_ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_MD_SETTINGS_UI_H_ -#include <unordered_set> - #include "base/macros.h" #include "base/time/time.h" #include "content/public/browser/web_contents_observer.h"
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn index 9cd3011..a813b89 100644 --- a/chrome/browser/vr/BUILD.gn +++ b/chrome/browser/vr/BUILD.gn
@@ -680,8 +680,10 @@ "//chrome/test:test_support", "//chrome/test:test_support_ui", "//device/vr:vr", + "//device/vr/buildflags:buildflags", "//device/vr/public/mojom:mojom", "//device/vr/public/mojom:test_mojom", + "//services/service_manager/sandbox", ] data_deps = []
diff --git a/chrome/browser/vr/test/webvr_browser_test.h b/chrome/browser/vr/test/webvr_browser_test.h index 1ee7466..418c29e 100644 --- a/chrome/browser/vr/test/webvr_browser_test.h +++ b/chrome/browser/vr/test/webvr_browser_test.h
@@ -5,11 +5,17 @@ #ifndef CHROME_BROWSER_VR_TEST_WEBVR_BROWSER_TEST_H_ #define CHROME_BROWSER_VR_TEST_WEBVR_BROWSER_TEST_H_ +#include "build/build_config.h" #include "chrome/browser/vr/test/webxr_vr_browser_test.h" #include "chrome/common/chrome_features.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" +#include "device/vr/buildflags/buildflags.h" + +#if defined(OS_WIN) +#include "services/service_manager/sandbox/features.h" +#endif namespace vr { @@ -37,6 +43,14 @@ public: WebVrBrowserTestOpenVrDisabled() { append_switches_.push_back(switches::kEnableWebVR); + +#if BUILDFLAG(ENABLE_WINDOWS_MR) + disable_features_.push_back(features::kWindowsMixedReality); +#endif + +#if defined(OS_WIN) + disable_features_.push_back(service_manager::features::kXRSandbox); +#endif } }; @@ -48,6 +62,14 @@ WebVrBrowserTestStandard() { append_switches_.push_back(switches::kEnableWebVR); enable_features_.push_back(features::kOpenVR); + +#if BUILDFLAG(ENABLE_WINDOWS_MR) + disable_features_.push_back(features::kWindowsMixedReality); +#endif + +#if defined(OS_WIN) + disable_features_.push_back(service_manager::features::kXRSandbox); +#endif } }; @@ -56,6 +78,14 @@ public: WebVrBrowserTestWebVrDisabled() { enable_features_.push_back(features::kOpenVR); + +#if BUILDFLAG(ENABLE_WINDOWS_MR) + disable_features_.push_back(features::kWindowsMixedReality); +#endif + +#if defined(OS_WIN) + disable_features_.push_back(service_manager::features::kXRSandbox); +#endif } }; #endif // OS_WIN
diff --git a/chrome/browser/vr/test/webxr_vr_browser_test.h b/chrome/browser/vr/test/webxr_vr_browser_test.h index fdc042a..644ce4c 100644 --- a/chrome/browser/vr/test/webxr_vr_browser_test.h +++ b/chrome/browser/vr/test/webxr_vr_browser_test.h
@@ -5,11 +5,17 @@ #ifndef CHROME_BROWSER_VR_TEST_WEBXR_VR_BROWSER_TEST_H_ #define CHROME_BROWSER_VR_TEST_WEBXR_VR_BROWSER_TEST_H_ +#include "build/build_config.h" #include "chrome/browser/vr/test/webxr_browser_test.h" #include "chrome/browser/vr/test/xr_browser_test.h" #include "chrome/common/chrome_features.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" +#include "device/vr/buildflags/buildflags.h" + +#if defined(OS_WIN) +#include "services/service_manager/sandbox/features.h" +#endif namespace vr { @@ -36,6 +42,14 @@ public: WebXrVrBrowserTestOpenVrDisabled() { enable_features_.push_back(features::kWebXr); + +#if BUILDFLAG(ENABLE_WINDOWS_MR) + disable_features_.push_back(features::kWindowsMixedReality); +#endif + +#if defined(OS_WIN) + disable_features_.push_back(service_manager::features::kXRSandbox); +#endif } }; @@ -47,6 +61,14 @@ WebXrVrBrowserTestStandard() { enable_features_.push_back(features::kOpenVR); enable_features_.push_back(features::kWebXr); + +#if BUILDFLAG(ENABLE_WINDOWS_MR) + disable_features_.push_back(features::kWindowsMixedReality); +#endif + +#if defined(OS_WIN) + disable_features_.push_back(service_manager::features::kXRSandbox); +#endif } }; @@ -55,6 +77,14 @@ public: WebXrVrBrowserTestWebXrDisabled() { enable_features_.push_back(features::kOpenVR); + +#if BUILDFLAG(ENABLE_WINDOWS_MR) + disable_features_.push_back(features::kWindowsMixedReality); +#endif + +#if defined(OS_WIN) + disable_features_.push_back(service_manager::features::kXRSandbox); +#endif } }; #endif // OS_WIN
diff --git a/chrome/browser/vr/test/xr_browser_test.cc b/chrome/browser/vr/test/xr_browser_test.cc index 13471f9..ae2ea5e 100644 --- a/chrome/browser/vr/test/xr_browser_test.cc +++ b/chrome/browser/vr/test/xr_browser_test.cc
@@ -40,6 +40,11 @@ constexpr char XrBrowserTestBase::kVrLogPathEnvVar[]; constexpr char XrBrowserTestBase::kVrLogPathVal[]; constexpr char XrBrowserTestBase::kTestFileDir[]; +const std::vector<std::string> XrBrowserTestBase::kRequiredTestSwitches{ + "enable-gpu", "enable-pixel-output-in-tests"}; +const std::vector<std::pair<std::string, std::string>> + XrBrowserTestBase::kRequiredTestSwitchesWithValues{ + std::pair<std::string, std::string>("test-launcher-jobs", "1")}; XrBrowserTestBase::XrBrowserTestBase() : env_(base::Environment::Create()) {} @@ -79,6 +84,24 @@ } void XrBrowserTestBase::SetUp() { + // Check whether the required flags were passed to the test - without these, + // we can fail in ways that are non-obvious, so fail more explicitly here if + // they aren't present. + auto* cmd_line = base::CommandLine::ForCurrentProcess(); + for (auto req_switch : kRequiredTestSwitches) { + ASSERT_TRUE(cmd_line->HasSwitch(req_switch)) + << "Missing switch " << req_switch << " required to run tests properly"; + } + for (auto req_switch_pair : kRequiredTestSwitchesWithValues) { + ASSERT_TRUE(cmd_line->HasSwitch(req_switch_pair.first)) + << "Missing switch " << req_switch_pair.first + << " required to run tests properly"; + ASSERT_TRUE(cmd_line->GetSwitchValueASCII(req_switch_pair.first) == + req_switch_pair.second) + << "Have required switch " << req_switch_pair.first + << ", but not required value " << req_switch_pair.second; + } + // Set the environment variable to use the mock OpenVR client. EXPECT_TRUE( env_->SetVar(kVrOverrideEnvVar, MakeExecutableRelative(kVrOverrideVal))) @@ -93,9 +116,9 @@ // Set any command line flags that subclasses have set, e.g. enabling WebVR // and OpenVR support. for (const auto& switch_string : append_switches_) { - base::CommandLine::ForCurrentProcess()->AppendSwitch(switch_string); + cmd_line->AppendSwitch(switch_string); } - scoped_feature_list_.InitWithFeatures(enable_features_, {}); + scoped_feature_list_.InitWithFeatures(enable_features_, disable_features_); InProcessBrowserTest::SetUp(); }
diff --git a/chrome/browser/vr/test/xr_browser_test.h b/chrome/browser/vr/test/xr_browser_test.h index 996d8df..dc9160c 100644 --- a/chrome/browser/vr/test/xr_browser_test.h +++ b/chrome/browser/vr/test/xr_browser_test.h
@@ -48,6 +48,9 @@ static constexpr char kVrLogPathVal[] = "./"; static constexpr char kTestFileDir[] = "chrome/test/data/xr/e2e_test_files/html/"; + static const std::vector<std::string> kRequiredTestSwitches; + static const std::vector<std::pair<std::string, std::string>> + kRequiredTestSwitchesWithValues; enum class TestStatus { STATUS_RUNNING = 0, STATUS_PASSED = 1, @@ -188,6 +191,7 @@ protected: std::unique_ptr<base::Environment> env_; std::vector<base::Feature> enable_features_; + std::vector<base::Feature> disable_features_; std::vector<std::string> append_switches_; private:
diff --git a/chrome/browser/web_applications/components/web_app_install_utils.cc b/chrome/browser/web_applications/components/web_app_install_utils.cc index 12ef100..db0e17f 100644 --- a/chrome/browser/web_applications/components/web_app_install_utils.cc +++ b/chrome/browser/web_applications/components/web_app_install_utils.cc
@@ -83,6 +83,9 @@ // we picked up from the web_app stuff. if (!web_app_icons.empty()) web_app_info->icons = std::move(web_app_icons); + + // Copy across the file handler info. + web_app_info->file_handler = manifest.file_handler; } std::set<int> SizesToGenerate() {
diff --git a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc index bf68681..8850575 100644 --- a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc +++ b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
@@ -35,6 +35,16 @@ manifest.short_name = base::NullableString16(base::UTF8ToUTF16(kAppShortName), false); + { + blink::Manifest::FileHandler file_handler; + blink::Manifest::FileFilter file; + file.accept.push_back(base::UTF8ToUTF16(".png")); + file.name = base::UTF8ToUTF16("Images"); + file_handler.push_back(file); + manifest.file_handler = + base::Optional<blink::Manifest::FileHandler>(std::move(file_handler)); + } + UpdateWebAppInfoFromManifest(manifest, &web_app_info, ForInstallableSite::kNo); EXPECT_EQ(base::UTF8ToUTF16(kAppShortName), web_app_info.title); @@ -67,6 +77,14 @@ EXPECT_EQ(2u, web_app_info.icons.size()); EXPECT_EQ(GURL(kAppIcon2), web_app_info.icons[0].url); EXPECT_EQ(GURL(kAppIcon3), web_app_info.icons[1].url); + + // Check file handlers were updated + EXPECT_TRUE(web_app_info.file_handler.has_value()); + auto file_handler = web_app_info.file_handler.value(); + EXPECT_EQ(1u, file_handler.size()); + EXPECT_EQ(base::UTF8ToUTF16("Images"), file_handler[0].name); + EXPECT_EQ(1u, file_handler[0].accept.size()); + EXPECT_EQ(base::UTF8ToUTF16(".png"), file_handler[0].accept[0]); } // Tests "scope" is only set for installable sites.
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 754ae59..8b269df6 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -295,7 +295,7 @@ #if BUILDFLAG(ENABLE_WINDOWS_MR) // Controls Windows Mixed Reality support. const base::Feature kWindowsMixedReality{"WindowsMixedReality", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; #endif // ENABLE_WINDOWS_MR #endif // BUILDFLAG(ENABLE_VR)
diff --git a/chrome/common/ppapi_utils.cc b/chrome/common/ppapi_utils.cc index e04512c..acfb297b 100644 --- a/chrome/common/ppapi_utils.cc +++ b/chrome/common/ppapi_utils.cc
@@ -114,6 +114,7 @@ #include "ppapi/thunk/interfaces_ppb_private_pdf.h" #include "ppapi/thunk/interfaces_ppb_public_dev.h" #include "ppapi/thunk/interfaces_ppb_public_dev_channel.h" +#include "ppapi/thunk/interfaces_ppb_public_socket.h" #include "ppapi/thunk/interfaces_ppb_public_stable.h" #undef PROXIED_IFACE
diff --git a/chrome/common/prerender_types.h b/chrome/common/prerender_types.h index b45242e..e6c98dc 100644 --- a/chrome/common/prerender_types.h +++ b/chrome/common/prerender_types.h
@@ -7,13 +7,6 @@ namespace prerender { -// PrerenderRelType is a bitfield since multiple rel attributes can be set -// on the same link. Must be the same as blink::WebPrerenderRelType. -enum PrerenderRelType { - PrerenderRelTypePrerender = 0x1, - PrerenderRelTypeNext = 0x2, -}; - enum PrerenderMode { // Neither prefetch nor prerender. NO_PRERENDER = 0,
diff --git a/chrome/common/web_application_info.h b/chrome/common/web_application_info.h index 34f7a49..a270efc 100644 --- a/chrome/common/web_application_info.h +++ b/chrome/common/web_application_info.h
@@ -11,6 +11,7 @@ #include "base/optional.h" #include "base/strings/string16.h" +#include "third_party/blink/public/common/manifest/manifest.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/size.h" @@ -66,6 +67,9 @@ // Whether the app should be opened in a window. If false, the app will be // opened in a tab. bool open_as_window; + + // The extensions and mime types the app can handle. + base::Optional<blink::Manifest::FileHandler> file_handler; }; #endif // CHROME_COMMON_WEB_APPLICATION_INFO_H_
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 65f05bc..cf6f7dd 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -214,6 +214,8 @@ const char kChromeUINetworkHost[] = "network"; const char kChromeUIOSCreditsHost[] = "os-credits"; const char kChromeUIOSCreditsURL[] = "chrome://os-credits/"; +const char kChromeUIOSSettingsHost[] = "os-settings"; +const char kChromeUIOSSettingsURL[] = "chrome://os-settings/"; const char kChromeUIOobeHost[] = "oobe"; const char kChromeUIOobeURL[] = "chrome://oobe/"; const char kChromeUIPowerHost[] = "power";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 002c96b..1a06412 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -209,6 +209,8 @@ extern const char kChromeUINetworkHost[]; extern const char kChromeUIOSCreditsHost[]; extern const char kChromeUIOSCreditsURL[]; +extern const char kChromeUIOSSettingsHost[]; +extern const char kChromeUIOSSettingsURL[]; extern const char kChromeUIOobeHost[]; extern const char kChromeUIOobeURL[]; extern const char kChromeUIPowerHost[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 8321735..667280d 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -867,7 +867,6 @@ "../browser/resource_coordinator/tab_activity_watcher_browsertest.cc", "../browser/resource_coordinator/tab_manager_browsertest.cc", "../browser/safe_browsing/chrome_cleaner/reporter_runner_browsertest_win.cc", - "../browser/safe_browsing/download_protection/download_protection_service_browsertest.cc", "../browser/safe_browsing/test_safe_browsing_database_helper.cc", "../browser/safe_browsing/test_safe_browsing_database_helper.h", "../browser/safe_json_parser_browsertest.cc",
diff --git a/chrome/test/data/extensions/api_test/file_browser/crostini_test/test.js b/chrome/test/data/extensions/api_test/file_browser/crostini_test/test.js index 0bb5c08..fb97a45 100644 --- a/chrome/test/data/extensions/api_test/file_browser/crostini_test/test.js +++ b/chrome/test/data/extensions/api_test/file_browser/crostini_test/test.js
@@ -52,16 +52,16 @@ chrome.fileManagerPrivate.getCrostiniSharedPaths(observeFirstForSession, chrome.test.callbackPass((entries, firstForSession) => { // 2 entries inserted in setup, and 1 successful entry added above. - chrome.test.assertEq(3, entries.length); - chrome.test.assertEq(urlPrefix + '/shared1', entries[0].toURL()); + chrome.test.assertEq(urlPrefix + '/share_dir', entries[0].toURL()); chrome.test.assertTrue(entries[0].isDirectory); - chrome.test.assertEq('/shared1', entries[0].fullPath); - chrome.test.assertEq(urlPrefix + '/shared2', entries[1].toURL()); + chrome.test.assertEq('/share_dir', entries[0].fullPath); + chrome.test.assertEq(3, entries.length); + chrome.test.assertEq(urlPrefix + '/shared1', entries[1].toURL()); chrome.test.assertTrue(entries[1].isDirectory); - chrome.test.assertEq('/shared2', entries[1].fullPath); - chrome.test.assertEq(urlPrefix + '/share_dir', entries[2].toURL()); + chrome.test.assertEq('/shared1', entries[1].fullPath); + chrome.test.assertEq(urlPrefix + '/shared2', entries[2].toURL()); chrome.test.assertTrue(entries[2].isDirectory); - chrome.test.assertEq('/share_dir', entries[2].fullPath); + chrome.test.assertEq('/shared2', entries[2].fullPath); // When observerFirstForSession is false, firstForSession is false. chrome.test.assertFalse(firstForSession); }));
diff --git a/chrome/test/data/local_ntp/custom_backgrounds_browsertest.js b/chrome/test/data/local_ntp/custom_backgrounds_browsertest.js index a98f61b..40b25b5e 100644 --- a/chrome/test/data/local_ntp/custom_backgrounds_browsertest.js +++ b/chrome/test/data/local_ntp/custom_backgrounds_browsertest.js
@@ -272,7 +272,7 @@ previewImageUrl: 'chrome-search://local-ntp/background.jpg' } ]; - coll_errors = {}; + collErrors = {}; }; // Append a call to onload to the end of the click handler. @@ -294,7 +294,7 @@ var oldImageLoader = $(tile_id).onclick; $(tile_id).onclick = function(event) { oldImageLoader(event); - coll_img = [ + collImg = [ { attributionActionUrl: 'https://www.google.com', attributions: ['test1', 'attribution1'], @@ -331,7 +331,7 @@ thumbnailImageUrl: 'chrome-search://local-ntp/background_thumbnail.jpg5' } ]; - coll_img_errors = {}; + collImgErrors = {}; $('ntp-images-loader').onload(); } }; @@ -346,8 +346,8 @@ let oldImageLoader = $(tile_id).onclick; $(tile_id).onclick = function(event) { oldImageLoader(event); - coll_img = []; - coll_img_errors = { net_error: true, net_error_no: -106 }; + collImg = []; + collImgErrors = {net_error: true, net_error_no: -106}; $('ntp-images-loader').onload(); } }; @@ -377,7 +377,7 @@ assertTrue(elementIsVisible($('bg-sel-menu'))); assertTrue($('bg-sel-menu').classList.contains('is-img-sel')); assertTrue( - document.getElementsByClassName('bg-sel-tile').length == coll_img.length); + document.getElementsByClassName('bg-sel-tile').length == collImg.length); assertTrue(elementIsVisible($('bg-sel-back'))); assertTrue(elementIsVisible($('bg-sel-footer-cancel'))); assertTrue(elementIsVisible($('bg-sel-footer-done')));
diff --git a/chrome/test/data/safe_browsing/download_protection/zipfile_two_archives.zip b/chrome/test/data/safe_browsing/download_protection/zipfile_two_archives.zip deleted file mode 100644 index d7af463..0000000 --- a/chrome/test/data/safe_browsing/download_protection/zipfile_two_archives.zip +++ /dev/null Binary files differ
diff --git a/chrome/test/data/safe_browsing/rar/has_two_archives.rar b/chrome/test/data/safe_browsing/rar/has_two_archives.rar deleted file mode 100644 index 416bd852..0000000 --- a/chrome/test/data/safe_browsing/rar/has_two_archives.rar +++ /dev/null Binary files differ
diff --git a/chrome/test/data/webui/settings/crostini_page_test.js b/chrome/test/data/webui/settings/crostini_page_test.js index d46b901..bdbe01a 100644 --- a/chrome/test/data/webui/settings/crostini_page_test.js +++ b/chrome/test/data/webui/settings/crostini_page_test.js
@@ -12,11 +12,11 @@ crostiniPage.prefs = { crostini: { enabled: {value: enabled}, - shared_paths: {value: opt_sharedPaths || []}, + }, + guest_os: { + paths_shared_to_vms: {value: opt_sharedPaths || {}}, } }; - crostiniBrowserProxy.enabled = enabled; - crostiniBrowserProxy.sharedPaths = opt_sharedPaths || []; crostiniBrowserProxy.sharedUsbDevices = opt_sharedUsbDevices || []; Polymer.dom.flush(); } @@ -54,8 +54,9 @@ button.click(); Polymer.dom.flush(); - setCrostiniPrefs(crostiniBrowserProxy.enabled); - assertTrue(crostiniPage.prefs.crostini.enabled.value); + assertEquals( + 1, crostiniBrowserProxy.getCallCount('requestCrostiniInstallerView')); + setCrostiniPrefs(true); assertTrue(!!crostiniPage.$$('.subpage-arrow')); }); @@ -146,8 +147,9 @@ test('Remove', function() { assertTrue(!!subpage.$$('#remove paper-button')); subpage.$$('#remove paper-button').click(); - setCrostiniPrefs(crostiniBrowserProxy.enabled); - assertFalse(crostiniPage.prefs.crostini.enabled.value); + assertEquals( + 1, crostiniBrowserProxy.getCallCount('requestRemoveCrostini')); + setCrostiniPrefs(false); return whenPopState().then(function() { assertEquals(settings.getCurrentRoute(), settings.routes.CROSTINI); assertTrue(!!crostiniPage.$$('#enable')); @@ -185,7 +187,7 @@ let subpage; setup(function() { - setCrostiniPrefs(true, crostiniBrowserProxy.sharedPaths); + setCrostiniPrefs(true, {'path1': ['termina'], 'path2': ['termina']}); return flushAsync().then(() => { settings.navigateTo(settings.routes.CROSTINI_SHARED_PATHS); return flushAsync().then(() => { @@ -206,9 +208,13 @@ assertTrue(!!subpage.$$('.list-item button')); // Remove first shared path, still one left. subpage.$$('.list-item button').click(); - assertEquals(1, crostiniBrowserProxy.sharedPaths.length); - setCrostiniPrefs(true, crostiniBrowserProxy.sharedPaths); - return flushAsync() + return crostiniBrowserProxy.whenCalled('removeCrostiniSharedPath') + .then(([vmName, path]) => { + assertEquals('termina', vmName); + assertEquals('path1', path); + setCrostiniPrefs(true, {'path2': ['termina']}); + return flushAsync(); + }) .then(() => { Polymer.dom.flush(); assertEquals( @@ -216,9 +222,14 @@ assertFalse(subpage.$.crostiniInstructionsRemove.hidden); // Remove remaining shared path, none left. + crostiniBrowserProxy.resetResolver('removeCrostiniSharedPath'); subpage.$$('.list-item button').click(); - assertEquals(0, crostiniBrowserProxy.sharedPaths.length); - setCrostiniPrefs(true, crostiniBrowserProxy.sharedPaths); + return crostiniBrowserProxy.whenCalled('removeCrostiniSharedPath'); + }) + .then(([vmName, path]) => { + assertEquals('termina', vmName); + assertEquals('path2', path); + setCrostiniPrefs(true, {}); return flushAsync(); }) .then(() => { @@ -235,7 +246,7 @@ let subpage; setup(function() { - setCrostiniPrefs(true, [], [ + setCrostiniPrefs(true, {}, [ {'shared': true, 'guid': '0001', 'name': 'usb_dev1'}, {'shared': false, 'guid': '0002', 'name': 'usb_dev2'}, {'shared': true, 'guid': '0003', 'name': 'usb_dev3'}
diff --git a/chrome/test/data/webui/settings/cups_printer_page_tests.js b/chrome/test/data/webui/settings/cups_printer_page_tests.js index 388946dc..02fabdd 100644 --- a/chrome/test/data/webui/settings/cups_printer_page_tests.js +++ b/chrome/test/data/webui/settings/cups_printer_page_tests.js
@@ -17,6 +17,7 @@ 'stopDiscoveringPrinters', 'cancelPrinterSetUp', 'updateCupsPrinter', + 'reconfigureCupsPrinter', ]); this.printerList = []; @@ -85,6 +86,11 @@ this.methodCalled('getPrinterPpdManufacturerAndModel', printerId); return Promise.resolve(this.printerPpdMakeModel); } + + /** @override */ + reconfigureCupsPrinter(printer) { + this.methodCalled('reconfigureCupsPrinter', printer); + } } suite('CupsAddPrinterDialogTests', function() { @@ -561,6 +567,7 @@ const nameField = dialog.$$('.printer-name-input'); assertTrue(!!nameField); nameField.value = 'edited printer'; + nameField.fire('input'); // Assert that the "Save" button is enabled. const saveButton = dialog.$$('.action-button'); @@ -600,6 +607,12 @@ const saveButton = dialog.$$('.action-button'); assertTrue(!!saveButton); + assertTrue(saveButton.disabled); + + // Change printer name to something valid. + printerName = dialog.$.printerName; + printerName.value = 'new printer name'; + printerName.fire('input'); assertFalse(saveButton.disabled); // Change printer address to something invalid. @@ -610,7 +623,7 @@ dialog.$.printerAddress.value = 'abcdef:1234'; assertFalse(saveButton.disabled); - // Change printer name to empty + // Change printer name to empty. dialog.$.printerName.value = ''; assertTrue(saveButton.disabled); }); @@ -637,7 +650,6 @@ printerQueue: 'moreinfohere', printerStatus: '', }; - setPpdManufacturerAndPpdModel('manufacture', 'model'); // Initializing activePrinter will set |needsReconfigured_| to true. Reset @@ -683,7 +695,6 @@ printerQueue: 'moreinfohere', printerStatus: '', }; - setPpdManufacturerAndPpdModel('manufacture', 'model'); // Initializing activePrinter will set |needsReconfigured_| to true. Reset @@ -711,10 +722,198 @@ const saveButton = dialog.$$('.action-button'); saveButton.click(); - return cupsPrintersBrowserProxy.whenCalled('addCupsPrinter') + return cupsPrintersBrowserProxy.whenCalled('reconfigureCupsPrinter') .then(function() { assertEquals(expectedAddress, dialog.activePrinter.printerAddress); assertEquals(expectedQueue, dialog.activePrinter.printerQueue); }); }); + + test('TestChangingNameEnablesSaveButton', function() { + dialog.activePrinter_ = { + ppdManufacturer: '', + ppdModel: '', + printerAddress: 'test:123', + printerAutoconf: false, + printerDescription: '', + printerId: 'id_123', + printerManufacturer: '', + printerModel: '', + printerMakeAndModel: '', + printerName: 'Test Printer', + printerPPDPath: '', + printerPpdReference: { + userSuppliedPpdUrl: '', + effectiveMakeAndModel: '', + autoconf: false, + }, + printerProtocol: 'ipp', + printerQueue: 'moreinfohere', + printerStatus: '', + }; + setPpdManufacturerAndPpdModel('manufacture', 'model'); + + const saveButton = dialog.$$('.action-button'); + assertTrue(!!saveButton); + assertTrue(saveButton.disabled); + + const nameField = dialog.$$('.printer-name-input'); + assertTrue(!!nameField); + nameField.value = 'edited printer'; + nameField.fire('input'); + + assertTrue(!saveButton.disabled); + }); + + test('TestChangingAddressEnablesSaveButton', function() { + dialog.activePrinter = { + ppdManufacturer: '', + ppdModel: '', + printerAddress: 'test:123', + printerAutoconf: false, + printerDescription: '', + printerId: 'id_123', + printerManufacturer: '', + printerModel: '', + printerMakeAndModel: '', + printerName: 'Test Printer', + printerPPDPath: '', + printerPpdReference: { + userSuppliedPpdUrl: '', + effectiveMakeAndModel: '', + autoconf: false, + }, + printerProtocol: 'ipp', + printerQueue: 'moreinfohere', + printerStatus: '', + }; + setPpdManufacturerAndPpdModel('manufacture', 'model'); + + const saveButton = dialog.$$('.action-button'); + assertTrue(!!saveButton); + assertTrue(saveButton.disabled); + + const addressField = dialog.$$('#printerAddress'); + assertTrue(!!addressField); + addressField.value = 'newAddress:789'; + addressField.fire('input'); + + assertTrue(!saveButton.disabled); + }); + + test('TestChangingQueueEnablesSaveButton', function() { + dialog.activePrinter = { + ppdManufacturer: '', + ppdModel: '', + printerAddress: 'test:123', + printerAutoconf: false, + printerDescription: '', + printerId: 'id_123', + printerManufacturer: '', + printerModel: '', + printerMakeAndModel: '', + printerName: 'Test Printer', + printerPPDPath: '', + printerPpdReference: { + userSuppliedPpdUrl: '', + effectiveMakeAndModel: '', + autoconf: false, + }, + printerProtocol: 'ipp', + printerQueue: 'moreinfohere', + printerStatus: '', + }; + setPpdManufacturerAndPpdModel('manufacture', 'model'); + + const saveButton = dialog.$$('.action-button'); + assertTrue(!!saveButton); + assertTrue(saveButton.disabled); + + const queueField = dialog.$$('#printerQueue'); + assertTrue(!!queueField); + queueField.value = 'newqueueinfo'; + queueField.fire('input'); + + assertTrue(!saveButton.disabled); + }); + + test('TestChangingProtocolEnablesSaveButton', function() { + dialog.activePrinter = { + ppdManufacturer: '', + ppdModel: '', + printerAddress: 'test:123', + printerAutoconf: false, + printerDescription: '', + printerId: 'id_123', + printerManufacturer: '', + printerModel: '', + printerMakeAndModel: '', + printerName: 'Test Printer', + printerPPDPath: '', + printerPpdReference: { + userSuppliedPpdUrl: '', + effectiveMakeAndModel: '', + autoconf: false, + }, + printerProtocol: 'ipp', + printerQueue: 'moreinfohere', + printerStatus: '', + }; + setPpdManufacturerAndPpdModel('manufacture', 'model'); + Polymer.dom.flush(); + + const saveButton = dialog.$$('.action-button'); + assertTrue(!!saveButton); + assertTrue(saveButton.disabled); + + const dropDown = dialog.$$('.md-select'); + dropDown.value = 'http'; + dropDown.dispatchEvent(new CustomEvent('change'), {'bubbles': true}); + Polymer.dom.flush(); + assertTrue(!saveButton.disabled); + }); + + test('TestChangingModelEnablesSaveButton', function() { + dialog.activePrinter = { + ppdManufacturer: '', + ppdModel: '', + printerAddress: 'test:123', + printerAutoconf: false, + printerDescription: '', + printerId: 'id_123', + printerManufacturer: '', + printerModel: '', + printerMakeAndModel: '', + printerName: 'Test Printer', + printerPPDPath: '', + printerPpdReference: { + userSuppliedPpdUrl: '', + effectiveMakeAndModel: '', + autoconf: false, + }, + printerProtocol: 'ipp', + printerQueue: 'moreinfohere', + printerStatus: '', + }; + setPpdManufacturerAndPpdModel('manufacture', 'model'); + // Printers are considered initialized for editing after PPD make/models + // are set. + dialog.arePrinterFieldsInitialized_ = true; + + const saveButton = dialog.$$('.action-button'); + assertTrue(!!saveButton); + assertTrue(saveButton.disabled); + + makeDropDown = dialog.$$('#printerPPDManufacturer'); + makeDropDown.value = 'HP'; + makeDropDown.dispatchEvent(new CustomEvent('change'), {'bubbles': true}); + // Saving is disabled until a model is selected. + assertTrue(saveButton.disabled); + + modelDropDown = dialog.$$('#printerPPDModel'); + modelDropDown.value = 'HP 910'; + modelDropDown.dispatchEvent(new CustomEvent('change'), {'bubbles': true}); + Polymer.dom.flush(); + assertTrue(!saveButton.disabled); + }); });
diff --git a/chrome/test/data/webui/settings/languages_page_tests.js b/chrome/test/data/webui/settings/languages_page_tests.js index bcc67124..6ccc6e31 100644 --- a/chrome/test/data/webui/settings/languages_page_tests.js +++ b/chrome/test/data/webui/settings/languages_page_tests.js
@@ -696,6 +696,15 @@ previousValue, languagesPage.prefs.spellcheck.use_spelling_service.value); }); + + test('disabling spell check turns off spelling service', () => { + languageHelper.setPrefValue('browser.enable_spellchecking', true); + languageHelper.setPrefValue('spellcheck.use_spelling_service', true); + languagesPage.$.enableSpellcheckingToggle.click(); + Polymer.dom.flush(); + assertFalse( + languageHelper.getPref('spellcheck.use_spelling_service').value); + }); }); });
diff --git a/chrome/test/data/webui/settings/people_page_test.js b/chrome/test/data/webui/settings/people_page_test.js index 573c02a..2817423 100644 --- a/chrome/test/data/webui/settings/people_page_test.js +++ b/chrome/test/data/webui/settings/people_page_test.js
@@ -125,7 +125,7 @@ // This makes sure UI meant for DICE-enabled profiles are not leaked to // non-dice profiles. - // TODO(scottchen): This should be removed once all profiles are fully + // TODO(tangltom): This should be removed once all profiles are fully // migrated. test('NoManageProfileRow', function() { assertFalse(!!peoplePage.$$('#edit-profile'));
diff --git a/chrome/test/data/webui/settings/personalization_options_test.js b/chrome/test/data/webui/settings/personalization_options_test.js index 1b67286..b0d7e6cc 100644 --- a/chrome/test/data/webui/settings/personalization_options_test.js +++ b/chrome/test/data/webui/settings/personalization_options_test.js
@@ -77,6 +77,17 @@ testElement.prefs = {spellcheck: {dictionaries: {value: []}}}; Polymer.dom.flush(); assertTrue(testElement.$.spellCheckControl.hidden); + + testElement.prefs = { + browser: {enable_spellchecking: {value: false}}, + spellcheck: { + dictionaries: {value: ['en-US']}, + use_spelling_service: {value: false} + } + }; + Polymer.dom.flush(); + testElement.$.spellCheckControl.click(); + assertTrue(testElement.prefs.spellcheck.use_spelling_service.value); }); test('NoUnifiedConsent spellcheck toggle', function() { @@ -88,6 +99,14 @@ testElement.prefs = {spellcheck: {dictionaries: {value: []}}}; Polymer.dom.flush(); assertFalse(testElement.$.spellCheckControl.hidden); + + testElement.prefs = { + browser: {enable_spellchecking: {value: false}}, + spellcheck: {use_spelling_service: {value: false}} + }; + Polymer.dom.flush(); + testElement.$.spellCheckControl.click(); + assertTrue(testElement.prefs.spellcheck.use_spelling_service.value); }); }); });
diff --git a/chrome/test/data/webui/settings/test_crostini_browser_proxy.js b/chrome/test/data/webui/settings/test_crostini_browser_proxy.js index a3f8597..af3ac42 100644 --- a/chrome/test/data/webui/settings/test_crostini_browser_proxy.js +++ b/chrome/test/data/webui/settings/test_crostini_browser_proxy.js
@@ -15,21 +15,17 @@ 'exportCrostiniContainer', 'importCrostiniContainer', ]); - this.enabled = false; - this.sharedPaths = ['path1', 'path2']; this.sharedUsbDevices = []; } /** @override */ requestCrostiniInstallerView() { this.methodCalled('requestCrostiniInstallerView'); - this.enabled = true; } /** override */ requestRemoveCrostini() { this.methodCalled('requestRemoveCrostini'); - this.enabled = false; } /** override */ @@ -50,9 +46,10 @@ } /** override */ - removeCrostiniSharedPath(path) { - this.sharedPaths = this.sharedPaths.filter(p => p !== path); + removeCrostiniSharedPath(vmName, path) { + this.methodCalled('removeCrostiniSharedPath', [vmName, path]); } + /** @override */ requestCrostiniInstallerStatus() { cr.webUIListenerCallback('crostini-installer-status-changed', false);
diff --git a/chrome/test/mini_installer/test_chrome_with_chromedriver.py b/chrome/test/mini_installer/test_chrome_with_chromedriver.py index d1706683..b492bb4 100644 --- a/chrome/test/mini_installer/test_chrome_with_chromedriver.py +++ b/chrome/test/mini_installer/test_chrome_with_chromedriver.py
@@ -136,6 +136,11 @@ def main(): + # DISABLING + # https://crbug.com/949727 + # DISABLING + return 0 + """Main entry point.""" parser = parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn index cf29b41..f2d1f96 100644 --- a/chromecast/BUILD.gn +++ b/chromecast/BUILD.gn
@@ -117,11 +117,7 @@ cast_media_unittests_filter = { test_name = "cast_media_unittests" - # TODO(almasrymina) : Track this test as a separate bug - # (internal : b/115400220) - gtest_excludes = [ "AudioVideoPipelineDeviceTest.Mp4Playback" ] - - gtest_excludes += vendor_cast_media_gtest_excludes + gtest_excludes = vendor_cast_media_gtest_excludes # --test-launcher-jobs=1 => so internal code can bind to port args = [ "--test-launcher-jobs=1" ]
diff --git a/chromecast/media/cma/backend/cplay/cplay.cc b/chromecast/media/cma/backend/cplay/cplay.cc index 5f319cf..f4bbaee5 100644 --- a/chromecast/media/cma/backend/cplay/cplay.cc +++ b/chromecast/media/cma/backend/cplay/cplay.cc
@@ -20,7 +20,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/no_destructor.h" -#include "base/numerics/range.h" +#include "base/numerics/ranges.h" #include "chromecast/media/cma/backend/cast_audio_json.h" #include "chromecast/media/cma/backend/cplay/wav_header.h" #include "chromecast/media/cma/backend/mixer_input.h" @@ -29,7 +29,7 @@ #include "chromecast/media/cma/backend/post_processing_pipeline_parser.h" #include "chromecast/media/cma/backend/volume_map.h" #include "chromecast/public/media/media_pipeline_backend.h" -#include "media/audio/sounds/wav_audio_handler.h" +#include "media/audio/wav_audio_handler.h" #include "media/base/audio_bus.h" #include "media/base/audio_sample_types.h" @@ -50,7 +50,7 @@ namespace { -const int kReadSize = 256; +const int kReadSize = 1024; void PrintHelp(const std::string& command) { LOG(INFO) << "Usage: " << command; @@ -298,15 +298,14 @@ auto factory = std::make_unique<PostProcessingPipelineFactoryImpl>(); auto pipeline = MixerPipeline::CreateMixerPipeline(&parser, factory.get()); CHECK(pipeline); - pipeline->Initialize(params.output_samples_per_second); + pipeline->Initialize(params.output_samples_per_second, kReadSize); LOG(INFO) << "Initialized Cast Audio Pipeline at " << params.output_samples_per_second << " samples per second"; // Add |input_source| to |pipeline| FilterGroup* input_group = pipeline->GetInputGroup(params.device_id); CHECK(input_group); - MixerInput mixer_input(&input_source, params.output_samples_per_second, - kReadSize, MixerInput::RenderingDelay(), input_group); + MixerInput mixer_input(&input_source, input_group); // Set volume. std::string contents;
diff --git a/chromecast/media/cma/backend/filter_group.cc b/chromecast/media/cma/backend/filter_group.cc index 208ad6e..8c3c678 100644 --- a/chromecast/media/cma/backend/filter_group.cc +++ b/chromecast/media/cma/backend/filter_group.cc
@@ -32,12 +32,37 @@ DCHECK_EQ(input->GetOutputChannelCount(), num_channels_); } -void FilterGroup::Initialize(int output_samples_per_second) { +void FilterGroup::AddStreamType(const std::string& stream_type) { + stream_types_.push_back(stream_type); +} + +void FilterGroup::Initialize(int output_samples_per_second, + int output_frames_per_write) { output_samples_per_second_ = output_samples_per_second; + output_frames_per_write_ = output_frames_per_write; + CHECK(post_processing_pipeline_->SetOutputSampleRate( output_samples_per_second_)); + input_samples_per_second_ = post_processing_pipeline_->GetInputSampleRate(); + input_frames_per_write_ = output_frames_per_write * + input_samples_per_second_ / + output_samples_per_second_; + DCHECK_EQ(input_frames_per_write_ * output_samples_per_second_, + output_frames_per_write_ * input_samples_per_second_) + << "Unable to produce stable buffer sizes for resampling rate " + << input_samples_per_second_ << " : " << output_samples_per_second_; + + for (FilterGroup* input : mixed_inputs_) { + input->Initialize(input_samples_per_second_, input_frames_per_write_); + } post_processing_pipeline_->SetContentType(content_type_); active_inputs_.clear(); + ResizeBuffers(); + + // Run a buffer of 0's to initialize rendering delay. + delay_seconds_ = post_processing_pipeline_->ProcessFrames( + interleaved_.get(), input_frames_per_write_, last_volume_, + true /* is_silence */); } void FilterGroup::AddInput(MixerInput* input) { @@ -52,11 +77,10 @@ } float FilterGroup::MixAndFilter( - int num_frames, + int num_output_frames, MediaPipelineBackend::AudioDecoder::RenderingDelay rendering_delay) { DCHECK_NE(output_samples_per_second_, 0); - - bool resize_needed = ResizeBuffersIfNecessary(num_frames); + DCHECK_EQ(num_output_frames, output_frames_per_write_); float volume = 0.0f; AudioContentType content_type = static_cast<AudioContentType>(-1); @@ -66,8 +90,8 @@ // Recursively mix inputs. for (auto* filter_group : mixed_inputs_) { - volume = std::max(volume, - filter_group->MixAndFilter(num_frames, rendering_delay)); + volume = std::max(volume, filter_group->MixAndFilter( + input_frames_per_write_, rendering_delay)); content_type = std::max(content_type, filter_group->content_type()); } @@ -78,17 +102,12 @@ // b) The output volume is 0 and has NEVER been non-zero, // since FilterGroup will use last_volume_ if volume is 0. // In this case, there was never any data in the pipeline. - // However, we still need to ensure that output buffers are initialized & - // large enough to hold |num_frames|, so we cannot use this shortcut if - // |resize_needed|. if (active_inputs_.empty() && volume == 0.0f && - !post_processing_pipeline_->IsRinging() && !resize_needed) { - if (frames_zeroed_ < num_frames) { - // Ensure OutputBuffer() is zeros. - // TODO(bshaya): Determine if this is necessary - if RingingTime is - // calculated correctly, then we could skip the fill_n. - std::fill_n(GetOutputBuffer(), num_frames * GetOutputChannelCount(), 0); - frames_zeroed_ = num_frames; + !post_processing_pipeline_->IsRinging()) { + if (frames_zeroed_ < num_output_frames) { + std::fill_n(GetOutputBuffer(), + num_output_frames * GetOutputChannelCount(), 0); + frames_zeroed_ = num_output_frames; } return 0.0f; // Output will be silence, no need to mix. } @@ -96,12 +115,13 @@ frames_zeroed_ = 0; // Mix InputQueues - mixed_->ZeroFramesPartial(0, num_frames); + mixed_->ZeroFramesPartial(0, input_frames_per_write_); for (MixerInput* input : active_inputs_) { DCHECK_LT(input->num_channels(), static_cast<int>(temp_buffers_.size())); DCHECK(temp_buffers_[input->num_channels()]); ::media::AudioBus* temp = temp_buffers_[input->num_channels()].get(); - int filled = input->FillAudioData(num_frames, rendering_delay, temp); + int filled = + input->FillAudioData(input_frames_per_write_, rendering_delay, temp); if (filled > 0) { int in_c = 0; for (int out_c = 0; out_c < num_channels_; ++out_c) { @@ -119,13 +139,13 @@ } mixed_->ToInterleaved<::media::FloatSampleTypeTraits<float>>( - num_frames, interleaved_.get()); + input_frames_per_write_, interleaved_.get()); // Mix FilterGroups for (FilterGroup* group : mixed_inputs_) { if (group->last_volume() > 0.0f) { - ::media::vector_math::FMAC(group->interleaved_.get(), 1.0f, - num_frames * num_channels_, + ::media::vector_math::FMAC(group->GetOutputBuffer(), 1.0f, + input_frames_per_write_ * num_channels_, interleaved_.get()); } } @@ -133,7 +153,7 @@ if (playout_channel_selection_ != kChannelAll) { // Duplicate selected channel to all channels. float* data = interleaved_.get(); - for (int f = 0; f < num_frames; ++f) { + for (int f = 0; f < input_frames_per_write_; ++f) { float selected = data[f * num_channels_ + playout_channel_selection_]; for (int c = 0; c < num_channels_; ++c) data[f * num_channels_ + c] = selected; @@ -155,7 +175,7 @@ } delay_seconds_ = post_processing_pipeline_->ProcessFrames( - interleaved_.get(), num_frames, last_volume_, is_silence); + interleaved_.get(), input_frames_per_write_, last_volume_, is_silence); return last_volume_; } @@ -175,23 +195,19 @@ return rendering_delay_to_output_; } -int FilterGroup::GetOutputChannelCount() { +int FilterGroup::GetOutputChannelCount() const { return post_processing_pipeline_->NumOutputChannels(); } -bool FilterGroup::ResizeBuffersIfNecessary(int num_frames) { - if (mixed_ && mixed_->frames() >= num_frames) { - return false; - } - mixed_ = ::media::AudioBus::Create(num_channels_, num_frames); +void FilterGroup::ResizeBuffers() { + mixed_ = ::media::AudioBus::Create(num_channels_, input_frames_per_write_); temp_buffers_.clear(); for (MixerInput* input : active_inputs_) { - AddTempBuffer(input->num_channels(), num_frames); + AddTempBuffer(input->num_channels(), input_frames_per_write_); } - interleaved_.reset(static_cast<float*>( - base::AlignedAlloc(num_frames * num_channels_ * sizeof(float), - ::media::AudioBus::kChannelAlignment))); - return true; + interleaved_.reset(static_cast<float*>(base::AlignedAlloc( + input_frames_per_write_ * num_channels_ * sizeof(float), + ::media::AudioBus::kChannelAlignment))); } void FilterGroup::AddTempBuffer(int num_channels, int num_frames) { @@ -223,13 +239,37 @@ } void FilterGroup::PrintTopology() const { - std::string input_groups; + std::string filter_groups; for (const FilterGroup* mixed_input : mixed_inputs_) { mixed_input->PrintTopology(); - input_groups += mixed_input->name() + ", "; + filter_groups += "[GROUP]" + mixed_input->name() + ", "; } - LOG(INFO) << input_groups << " -> " << num_channels_ << "ch -> " << name_; + std::string input_groups; + for (const std::string& stream_type : stream_types_) { + input_groups += "[STREAM]" + stream_type + ", "; + } + + // Trim trailing comma. + if (!filter_groups.empty()) { + filter_groups.resize(filter_groups.size() - 2); + } + if (!input_groups.empty()) { + input_groups.resize(input_groups.size() - 2); + } + + std::string all_inputs; + if (filter_groups.empty()) { + all_inputs = input_groups; + } else if (input_groups.empty()) { + all_inputs = filter_groups; + } else { + all_inputs = input_groups + " + " + filter_groups; + } + LOG(INFO) << all_inputs << ": " << num_channels_ << "ch@" + << input_samples_per_second_ << "hz -> [GROUP]" << name_ << " -> " + << GetOutputChannelCount() << "ch@" << output_samples_per_second_ + << "hz"; } } // namespace media
diff --git a/chromecast/media/cma/backend/filter_group.h b/chromecast/media/cma/backend/filter_group.h index 8158f35..3f81c982 100644 --- a/chromecast/media/cma/backend/filter_group.h +++ b/chromecast/media/cma/backend/filter_group.h
@@ -50,8 +50,16 @@ // than one FilterGroup will result in incorrect behavior. void AddMixedInput(FilterGroup* input); - // Sets the sample rate of the post-processors. - void Initialize(int output_samples_per_second); + // Recursively sets the sample rate of the post-processors and FilterGroups. + // This should only be called externally on the output node of the FilterGroup + // tree. + // The output rate of this group will be |output_samples_per_second|. + // The output block size, i.e. the number of frames written in each call to + // MixAndFilter() of this group will be |output_frames_per_write|. + // Groups that feed this group may receive different values due to resampling. + // After calling Initialize(), input_samples_per_second() and + // input_frames_per_write() may be called to determine the input rate/size. + void Initialize(int output_samples_per_second, int output_frames_per_write); // Adds/removes |input| from |active_inputs_|. void AddInput(MixerInput* input); @@ -85,7 +93,10 @@ std::string name() const { return name_; } // Returns number of audio output channels from the filter group. - int GetOutputChannelCount(); + int GetOutputChannelCount() const; + + // Returns the expected sample rate for inputs to this group. + int GetInputSampleRate() const { return input_samples_per_second_; } // Sends configuration string |config| to all post processors with the given // |name|. @@ -101,19 +112,28 @@ // Recursively print the layout of the pipeline. void PrintTopology() const; + // Add |stream_type| to the list of streams this processor handles. + void AddStreamType(const std::string& stream_type); + + int input_frames_per_write() const { return input_frames_per_write_; } + int input_samples_per_second() const { return input_samples_per_second_; } + private: - // Resizes temp_ and mixed_ if they are too small to hold |num_frames| frames. - // Returns |true| if |num_frames| is larger than all previous |num_frames|. - bool ResizeBuffersIfNecessary(int num_frames); + // Resizes temp_buffers_ and mixed_. + void ResizeBuffers(); void AddTempBuffer(int num_channels, int num_frames); const int num_channels_; const std::string name_; std::vector<FilterGroup*> mixed_inputs_; + std::vector<std::string> stream_types_; base::flat_set<MixerInput*> active_inputs_; int playout_channel_selection_ = kChannelAll; int output_samples_per_second_ = 0; + int input_samples_per_second_ = 0; + int output_frames_per_write_ = 0; + int input_frames_per_write_ = 0; int frames_zeroed_ = 0; float last_volume_ = 0.0; double delay_seconds_ = 0;
diff --git a/chromecast/media/cma/backend/filter_group_unittest.cc b/chromecast/media/cma/backend/filter_group_unittest.cc index 9b74560..5582dc2 100644 --- a/chromecast/media/cma/backend/filter_group_unittest.cc +++ b/chromecast/media/cma/backend/filter_group_unittest.cc
@@ -65,10 +65,10 @@ sample_rate_ = sample_rate; return true; } - int GetInputSampleRate() { return sample_rate_; } + int GetInputSampleRate() const override { return sample_rate_; } bool IsRinging() override { return false; } float* GetOutputBuffer() override { return output_buffer_; } - int NumOutputChannels() override { return num_output_channels_; } + int NumOutputChannels() const override { return num_output_channels_; } int delay() { return 0; } std::string name() const { return "mock"; } double StorePtr(float* data, @@ -125,7 +125,7 @@ sample_rate_ = sample_rate; return true; } - int GetInputSampleRate() override { return sample_rate_; } + int GetInputSampleRate() const override { return sample_rate_; } bool IsRinging() override { return false; } int delay() { return 0; } @@ -170,9 +170,7 @@ class FilterGroupTest : public testing::Test { protected: using RenderingDelay = MixerInput::RenderingDelay; - FilterGroupTest() - : source_(kInputSampleRate), - input_(&source_, kInputSampleRate, 0, RenderingDelay(), nullptr) { + FilterGroupTest() : source_(kInputSampleRate) { source_.SetData(GetTestData()); } @@ -185,8 +183,9 @@ EXPECT_CALL(*post_processor_, UpdatePlayoutChannel(kDefaultPlayoutChannel)); filter_group_ = std::make_unique<FilterGroup>( kNumInputChannels, "test_filter", std::move(post_processor)); - filter_group_->Initialize(kInputSampleRate); - filter_group_->AddInput(&input_); + input_ = std::make_unique<MixerInput>(&source_, filter_group_.get()); + filter_group_->Initialize(kInputSampleRate, kInputFrames); + filter_group_->AddInput(input_.get()); filter_group_->UpdatePlayoutChannel(kChannelAll); } @@ -211,8 +210,8 @@ float RightInput(int frame) { return Input(1, frame); } NiceMock<MockMixerSource> source_; - MixerInput input_; std::unique_ptr<FilterGroup> filter_group_; + std::unique_ptr<MixerInput> input_; MockPostProcessingPipeline* post_processor_ = nullptr; private: @@ -254,13 +253,11 @@ NiceMock<MockMixerSource> tts_source(kInputSampleRate); tts_source.set_content_type(AudioContentType::kCommunication); - MixerInput tts_input(&tts_source, kInputSampleRate, 0, RenderingDelay(), - nullptr); + MixerInput tts_input(&tts_source, filter_group_.get()); NiceMock<MockMixerSource> alarm_source(kInputSampleRate); alarm_source.set_content_type(AudioContentType::kAlarm); - MixerInput alarm_input(&alarm_source, kInputSampleRate, 0, RenderingDelay(), - nullptr); + MixerInput alarm_input(&alarm_source, filter_group_.get()); // Media input stream + tts input stream -> tts content type. filter_group_->AddInput(&tts_input);
diff --git a/chromecast/media/cma/backend/mixer_input.cc b/chromecast/media/cma/backend/mixer_input.cc index 6a80a06..9ffb1ed4 100644 --- a/chromecast/media/cma/backend/mixer_input.cc +++ b/chromecast/media/cma/backend/mixer_input.cc
@@ -34,15 +34,11 @@ } // namespace -MixerInput::MixerInput(Source* source, - int output_samples_per_second, - int read_size, - RenderingDelay initial_rendering_delay, - FilterGroup* filter_group) +MixerInput::MixerInput(Source* source, FilterGroup* filter_group) : source_(source), num_channels_(source->num_channels()), input_samples_per_second_(source->input_samples_per_second()), - output_samples_per_second_(output_samples_per_second), + output_samples_per_second_(filter_group->input_samples_per_second()), primary_(source->primary()), device_id_(source->device_id()), content_type_(source->content_type()), @@ -58,7 +54,10 @@ DCHECK_GT(num_channels_, 0); DCHECK_GT(input_samples_per_second_, 0); - int source_read_size = read_size; + MediaPipelineBackend::AudioDecoder::RenderingDelay initial_rendering_delay = + filter_group->GetRenderingDelayToOutput(); + + int source_read_size = filter_group->input_frames_per_write(); if (output_samples_per_second_ > 0 && output_samples_per_second_ != input_samples_per_second_) { // Round up to nearest multiple of SincResampler::kKernelSize. The read size
diff --git a/chromecast/media/cma/backend/mixer_input.h b/chromecast/media/cma/backend/mixer_input.h index 6a5c16c..8707e8d 100644 --- a/chromecast/media/cma/backend/mixer_input.h +++ b/chromecast/media/cma/backend/mixer_input.h
@@ -82,9 +82,6 @@ }; MixerInput(Source* source, - int output_samples_per_second, - int read_size, - RenderingDelay initial_rendering_delay, FilterGroup* filter_group); ~MixerInput();
diff --git a/chromecast/media/cma/backend/mixer_pipeline.cc b/chromecast/media/cma/backend/mixer_pipeline.cc index 4f8656a8..3c377bc 100644 --- a/chromecast/media/cma/backend/mixer_pipeline.cc +++ b/chromecast/media/cma/backend/mixer_pipeline.cc
@@ -126,8 +126,6 @@ loopback_output_group_; } - output_group_->PrintTopology(); - return true; } @@ -155,14 +153,17 @@ return false; } stream_sinks_[stream_type] = filter_group; + filter_group->AddStreamType(stream_type); } return true; } -void MixerPipeline::Initialize(int output_samples_per_second_) { - for (auto&& filter_group : filter_groups_) { - filter_group->Initialize(output_samples_per_second_); - } +void MixerPipeline::Initialize(int output_samples_per_second, + int frames_per_write) { + // The output group will recursively set the sample rate of all other + // FilterGroups. + output_group_->Initialize(output_samples_per_second, frames_per_write); + output_group_->PrintTopology(); } FilterGroup* MixerPipeline::GetInputGroup(const std::string& device_id) {
diff --git a/chromecast/media/cma/backend/mixer_pipeline.h b/chromecast/media/cma/backend/mixer_pipeline.h index 779dd19..5e9bf67 100644 --- a/chromecast/media/cma/backend/mixer_pipeline.h +++ b/chromecast/media/cma/backend/mixer_pipeline.h
@@ -41,7 +41,7 @@ ~MixerPipeline(); // Sets the sample rate of all processors. - void Initialize(int samples_per_second); + void Initialize(int samples_per_second, int frames_per_write); // Returns the FilterGroup that should process a stream with |device_id| or // |nullptr| if no matching FilterGroup is found.
diff --git a/chromecast/media/cma/backend/mock_post_processor_factory.h b/chromecast/media/cma/backend/mock_post_processor_factory.h index c8a66e0..22b4f7f 100644 --- a/chromecast/media/cma/backend/mock_post_processor_factory.h +++ b/chromecast/media/cma/backend/mock_post_processor_factory.h
@@ -38,12 +38,12 @@ sample_rate_ = sample_rate; return true; } - int GetInputSampleRate() override { return sample_rate_; } + int GetInputSampleRate() const override { return sample_rate_; } bool IsRinging() override { return ringing_; } int delay() { return rendering_delay_frames_; } std::string name() const { return name_; } float* GetOutputBuffer() override { return output_buffer_; } - int NumOutputChannels() override { return num_output_channels_; } + int NumOutputChannels() const override { return num_output_channels_; } MOCK_METHOD2(SetPostProcessorConfig, void(const std::string& name, const std::string& config));
diff --git a/chromecast/media/cma/backend/post_processing_pipeline.h b/chromecast/media/cma/backend/post_processing_pipeline.h index f20e301..d0a5cbd 100644 --- a/chromecast/media/cma/backend/post_processing_pipeline.h +++ b/chromecast/media/cma/backend/post_processing_pipeline.h
@@ -27,10 +27,10 @@ float current_multiplier, bool is_silence) = 0; virtual float* GetOutputBuffer() = 0; - virtual int NumOutputChannels() = 0; + virtual int NumOutputChannels() const = 0; virtual bool SetOutputSampleRate(int sample_rate) = 0; - virtual int GetInputSampleRate() = 0; + virtual int GetInputSampleRate() const = 0; virtual bool IsRinging() = 0; virtual void SetPostProcessorConfig(const std::string& name, const std::string& config) = 0;
diff --git a/chromecast/media/cma/backend/post_processing_pipeline_impl.cc b/chromecast/media/cma/backend/post_processing_pipeline_impl.cc index 0f9284c..90fcf65 100644 --- a/chromecast/media/cma/backend/post_processing_pipeline_impl.cc +++ b/chromecast/media/cma/backend/post_processing_pipeline_impl.cc
@@ -104,10 +104,10 @@ LOG(INFO) << "Creating an instance of " << library_path << "(" << processor_config_string << ")"; - processors_.emplace_back( - PostProcessorInfo{factory_.CreatePostProcessor( - library_path, processor_config_string, channels), - processor_name}); + processors_.emplace_back(PostProcessorInfo{ + factory_.CreatePostProcessor(library_path, processor_config_string, + channels), + 1.0 /* output_frames_per_input_frame */, processor_name}); channels = processors_.back().ptr->GetStatus().output_channels; } num_output_channels_ = channels; @@ -116,7 +116,7 @@ PostProcessingPipelineImpl::~PostProcessingPipelineImpl() = default; double PostProcessingPipelineImpl::ProcessFrames(float* data, - int num_frames, + int num_input_frames, float current_multiplier, bool is_silence) { DCHECK_GT(input_sample_rate_, 0); @@ -128,7 +128,7 @@ if (!IsRinging()) { return delay_s_; // Output will be silence. } - silence_frames_processed_ += num_frames; + silence_frames_processed_ += num_input_frames; } else { silence_frames_processed_ = 0; } @@ -137,8 +137,12 @@ delay_s_ = 0; for (auto& processor : processors_) { - processor.ptr->ProcessFrames(output_buffer_, num_frames, cast_volume_, + processor.ptr->ProcessFrames(output_buffer_, num_input_frames, cast_volume_, current_dbfs_); + DCHECK_EQ( + num_input_frames * processor.output_frames_per_input_frame, + std::floor(num_input_frames * processor.output_frames_per_input_frame)); + num_input_frames *= processor.output_frames_per_input_frame; const auto& status = processor.ptr->GetStatus(); delay_s_ += static_cast<double>(status.rendering_delay_frames) / status.input_sample_rate; @@ -147,7 +151,7 @@ return delay_s_; } -int PostProcessingPipelineImpl::NumOutputChannels() { +int PostProcessingPipelineImpl::NumOutputChannels() const { return num_output_channels_; } @@ -159,23 +163,30 @@ bool PostProcessingPipelineImpl::SetOutputSampleRate(int sample_rate) { output_sample_rate_ = sample_rate; - input_sample_rate_ = sample_rate; + int processor_output_rate = sample_rate; + int processor_input_rate = sample_rate; // Each Processor's output rate must be the following processor's input rate. - for (int i = processors_.size() - 1; i >= 0; --i) { + for (int i = static_cast<int>(processors_.size()) - 1; i >= 0; --i) { AudioPostProcessor2::Config config; - config.output_sample_rate = input_sample_rate_; + config.output_sample_rate = processor_output_rate; if (!processors_[i].ptr->SetConfig(config)) { return false; } - input_sample_rate_ = processors_[i].ptr->GetStatus().input_sample_rate; + processor_input_rate = processors_[i].ptr->GetStatus().input_sample_rate; + DCHECK_GT(processor_input_rate, 0) << processors_[i].name; + processors_[i].output_frames_per_input_frame = + static_cast<double>(processor_output_rate) / processor_input_rate; + processor_output_rate = processor_input_rate; } + + input_sample_rate_ = processor_input_rate; ringing_time_in_frames_ = GetRingingTimeInFrames(); silence_frames_processed_ = 0; return true; } -int PostProcessingPipelineImpl::GetInputSampleRate() { +int PostProcessingPipelineImpl::GetInputSampleRate() const { return input_sample_rate_; } @@ -218,8 +229,8 @@ [&name](PostProcessorInfo& p) { return p.name == name; }); if (it != processors_.end()) { it->ptr->UpdateParameters(config); - LOG(INFO) << "Config string: " << config - << " was delivered to postprocessor " << name; + DVLOG(2) << "Config string: " << config + << " was delivered to postprocessor " << name; } }
diff --git a/chromecast/media/cma/backend/post_processing_pipeline_impl.h b/chromecast/media/cma/backend/post_processing_pipeline_impl.h index a87bf7b8..31ad0e2 100644 --- a/chromecast/media/cma/backend/post_processing_pipeline_impl.h +++ b/chromecast/media/cma/backend/post_processing_pipeline_impl.h
@@ -38,10 +38,10 @@ bool is_silence) override; float* GetOutputBuffer() override; - int NumOutputChannels() override; + int NumOutputChannels() const override; bool SetOutputSampleRate(int sample_rate) override; - int GetInputSampleRate() override; + int GetInputSampleRate() const override; bool IsRinging() override; // Send string |config| to post processor |name|. @@ -55,6 +55,7 @@ // structs. typedef struct { std::unique_ptr<AudioPostProcessor2> ptr; + double output_frames_per_input_frame; std::string name; } PostProcessorInfo;
diff --git a/chromecast/media/cma/backend/post_processors/post_processor_wrapper.cc b/chromecast/media/cma/backend/post_processors/post_processor_wrapper.cc index ee7858f..b51d5a3 100644 --- a/chromecast/media/cma/backend/post_processors/post_processor_wrapper.cc +++ b/chromecast/media/cma/backend/post_processors/post_processor_wrapper.cc
@@ -29,7 +29,7 @@ bool AudioPostProcessorWrapper::SetConfig( const AudioPostProcessor2::Config& config) { - if (!pp_->SetSampleRate(status_.input_sample_rate)) { + if (!pp_->SetSampleRate(config.output_sample_rate)) { return false; } status_.input_sample_rate = config.output_sample_rate;
diff --git a/chromecast/media/cma/backend/stream_mixer.cc b/chromecast/media/cma/backend/stream_mixer.cc index 728d790c..529748d 100644 --- a/chromecast/media/cma/backend/stream_mixer.cc +++ b/chromecast/media/cma/backend/stream_mixer.cc
@@ -120,7 +120,7 @@ task_runner->PostTask(FROM_HERE, std::move(task)); } -int GetFixedSampleRate() { +int GetFixedOutputSampleRate() { int fixed_sample_rate = GetSwitchValueNonNegativeInt( switches::kAudioOutputSampleRate, MixerOutputStream::kInvalidSampleRate); @@ -186,7 +186,7 @@ GetSwitchValueBoolean(switches::kAlsaEnableUpsampling, false) ? kLowSampleRateCutoff : MixerOutputStream::kInvalidSampleRate), - fixed_sample_rate_(GetFixedSampleRate()), + fixed_output_sample_rate_(GetFixedOutputSampleRate()), no_input_close_timeout_(GetNoInputCloseTimeout()), filter_frame_alignment_(kDefaultFilterFrameAlignment), state_(kStateStopped), @@ -226,8 +226,8 @@ input_task_runner_ = mixer_task_runner_; } - if (fixed_sample_rate_ != MixerOutputStream::kInvalidSampleRate) { - LOG(INFO) << "Setting fixed sample rate to " << fixed_sample_rate_; + if (fixed_output_sample_rate_ != MixerOutputStream::kInvalidSampleRate) { + LOG(INFO) << "Setting fixed sample rate to " << fixed_output_sample_rate_; } CreatePostProcessors([](bool, const std::string&) {}, @@ -314,7 +314,7 @@ CHECK(PostProcessorsHaveCorrectNumOutputs()); if (state_ == kStateRunning) { - mixer_pipeline_->Initialize(output_samples_per_second_); + mixer_pipeline_->Initialize(output_samples_per_second_, frames_per_write_); } if (callback) { @@ -383,8 +383,8 @@ DCHECK(output_); int requested_sample_rate; - if (fixed_sample_rate_ != MixerOutputStream::kInvalidSampleRate) { - requested_sample_rate = fixed_sample_rate_; + if (fixed_output_sample_rate_ != MixerOutputStream::kInvalidSampleRate) { + requested_sample_rate = fixed_output_sample_rate_; } else if (low_sample_rate_cutoff_ != MixerOutputStream::kInvalidSampleRate && requested_output_samples_per_second_ < low_sample_rate_cutoff_) { requested_sample_rate = @@ -407,7 +407,7 @@ CHECK_GT(frames_per_write_, 0); // Initialize filters. - mixer_pipeline_->Initialize(output_samples_per_second_); + mixer_pipeline_->Initialize(output_samples_per_second_, frames_per_write_); for (auto& redirector : audio_output_redirectors_) { redirector.second->Start(output_samples_per_second_); @@ -491,7 +491,7 @@ // may need to change the output sample rate to match the input sample rate. // We only change the output rate if it is not set to a fixed value. if ((input_source->primary() || inputs_.empty()) && - fixed_sample_rate_ == MixerOutputStream::kInvalidSampleRate) { + fixed_output_sample_rate_ == MixerOutputStream::kInvalidSampleRate) { CheckChangeOutputRate(input_source->input_samples_per_second()); } @@ -506,11 +506,11 @@ DCHECK(input_group) << "Could not find a processor for " << input_source->device_id(); - LOG(INFO) << "Add input " << input_source << " to " << input_group->name(); + LOG(INFO) << "Add input " << input_source << " to " << input_group->name() + << " @ " << input_group->GetInputSampleRate() + << " samples per second."; - auto input = std::make_unique<MixerInput>( - input_source, output_samples_per_second_, frames_per_write_, - GetTotalRenderingDelay(input_group), input_group); + auto input = std::make_unique<MixerInput>(input_source, input_group); if (state_ != kStateRunning) { // Mixer error occurred, signal error. MixerInput* input_ptr = input.get();
diff --git a/chromecast/media/cma/backend/stream_mixer.h b/chromecast/media/cma/backend/stream_mixer.h index 19111ef..66ebb376 100644 --- a/chromecast/media/cma/backend/stream_mixer.h +++ b/chromecast/media/cma/backend/stream_mixer.h
@@ -238,7 +238,7 @@ int num_output_channels_; const int low_sample_rate_cutoff_; - const int fixed_sample_rate_; + const int fixed_output_sample_rate_; const base::TimeDelta no_input_close_timeout_; // Force data to be filtered in multiples of |filter_frame_alignment_| frames. // Must be a multiple of 4 for some NEON implementations. Some
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index 13c0d28..55b487a 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn
@@ -36,9 +36,7 @@ "//chromeos/dbus/constants", "//components/policy/proto", "//google_apis", - "//services/device/public/mojom", "//services/network/public/cpp:cpp", - "//services/service_manager/public/cpp", "//third_party/protobuf:protobuf_lite", ] sources = [ @@ -74,8 +72,6 @@ "process_proxy/process_proxy_registry.h", "system/cpu_temperature_reader.cc", "system/cpu_temperature_reader.h", - "system/dark_resume_controller.cc", - "system/dark_resume_controller.h", "system/devicemode.cc", "system/devicemode.h", "system/factory_ping_embargo_check.cc", @@ -183,11 +179,8 @@ "//mojo/core/embedder", "//net", "//net:test_support", - "//services/device/public/cpp/test:test_support", - "//services/device/public/mojom", "//services/network:test_support", "//services/network/public/cpp", - "//services/service_manager/public/cpp/test:test_support", "//testing/gmock", "//testing/gtest", "//third_party/icu", @@ -207,7 +200,6 @@ "process_proxy/process_output_watcher_unittest.cc", "process_proxy/process_proxy_unittest.cc", "system/cpu_temperature_reader_unittest.cc", - "system/dark_resume_controller_unittest.cc", "system/factory_ping_embargo_check_unittest.cc", "system/name_value_pairs_parser_unittest.cc", "test/run_all_unittests.cc",
diff --git a/chromeos/components/BUILD.gn b/chromeos/components/BUILD.gn index 708e751..13050e2 100644 --- a/chromeos/components/BUILD.gn +++ b/chromeos/components/BUILD.gn
@@ -21,6 +21,7 @@ "//chromeos/components/drivefs:unit_tests", "//chromeos/components/multidevice:unit_tests", "//chromeos/components/nearby:unit_tests", + "//chromeos/components/power:unit_tests", "//chromeos/components/proximity_auth:unit_tests", "//chromeos/components/tether:unit_tests", "//mojo/core/embedder",
diff --git a/chromeos/components/power/BUILD.gn b/chromeos/components/power/BUILD.gn new file mode 100644 index 0000000..f45b728 --- /dev/null +++ b/chromeos/components/power/BUILD.gn
@@ -0,0 +1,42 @@ +# 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. + +assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos") + +component("power") { + output_name = "chromeos_power" + defines = [ "IS_CHROMEOS_POWER_IMPL" ] + deps = [ + "//base", + + # TODO(stevenjb): Replace this with //chromeos/dbus/power once extracted. + # https://crbug.com/644348. + "//chromeos/dbus", + "//services/device/public/mojom", + "//services/service_manager/public/cpp", + ] + + sources = [ + "dark_resume_controller.cc", + "dark_resume_controller.h", + ] +} + +source_set("unit_tests") { + testonly = true + + sources = [ + "dark_resume_controller_unittest.cc", + ] + + deps = [ + ":power", + "//base/test:test_support", + "//chromeos/dbus", + "//services/device/public/cpp/test:test_support", + "//services/device/public/mojom", + "//services/service_manager/public/cpp/test:test_support", + "//testing/gtest", + ] +}
diff --git a/chromeos/system/dark_resume_controller.cc b/chromeos/components/power/dark_resume_controller.cc similarity index 98% rename from chromeos/system/dark_resume_controller.cc rename to chromeos/components/power/dark_resume_controller.cc index 09bcc52..0782ee9 100644 --- a/chromeos/system/dark_resume_controller.cc +++ b/chromeos/components/power/dark_resume_controller.cc
@@ -1,7 +1,7 @@ // 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 "chromeos/system/dark_resume_controller.h" +#include "chromeos/components/power/dark_resume_controller.h" #include <utility>
diff --git a/chromeos/system/dark_resume_controller.h b/chromeos/components/power/dark_resume_controller.h similarity index 94% rename from chromeos/system/dark_resume_controller.h rename to chromeos/components/power/dark_resume_controller.h index 3004f34..9655795 100644 --- a/chromeos/system/dark_resume_controller.h +++ b/chromeos/components/power/dark_resume_controller.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROMEOS_SYSTEM_DARK_RESUME_CONTROLLER_H_ -#define CHROMEOS_SYSTEM_DARK_RESUME_CONTROLLER_H_ +#ifndef CHROMEOS_COMPONENTS_POWER_DARK_RESUME_CONTROLLER_H_ +#define CHROMEOS_COMPONENTS_POWER_DARK_RESUME_CONTROLLER_H_ #include <memory> +#include "base/component_export.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" -#include "chromeos/chromeos_export.h" #include "chromeos/dbus/power/power_manager_client.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/device/public/mojom/wake_lock.mojom.h" @@ -43,7 +43,7 @@ // // 5. If the system transitions to a full resume all dark resume related state // and timers are cleared as the system wakes up. -class CHROMEOS_EXPORT DarkResumeController +class COMPONENT_EXPORT(CHROMEOS_POWER) DarkResumeController : public chromeos::PowerManagerClient::Observer, public device::mojom::WakeLockObserver { public: @@ -129,4 +129,4 @@ } // namespace system } // namespace chromeos -#endif // CHROMEOS_SYSTEM_DARK_RESUME_CONTROLLER_H_ +#endif // CHROMEOS_COMPONENTS_POWER_DARK_RESUME_CONTROLLER_H_
diff --git a/chromeos/system/dark_resume_controller_unittest.cc b/chromeos/components/power/dark_resume_controller_unittest.cc similarity index 98% rename from chromeos/system/dark_resume_controller_unittest.cc rename to chromeos/components/power/dark_resume_controller_unittest.cc index 71f3f55..7ba188b9 100644 --- a/chromeos/system/dark_resume_controller_unittest.cc +++ b/chromeos/components/power/dark_resume_controller_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 "chromeos/system/dark_resume_controller.h" +#include "chromeos/components/power/dark_resume_controller.h" #include <memory> #include <utility>
diff --git a/components/download/quarantine/quarantine_win.cc b/components/download/quarantine/quarantine_win.cc index bd4827c..59701ee 100644 --- a/components/download/quarantine/quarantine_win.cc +++ b/components/download/quarantine/quarantine_win.cc
@@ -92,6 +92,39 @@ : QuarantineFileResult::ANNOTATION_FAILED; } +// Maps a return code from an unsuccessful IAttachmentExecute::Save() call to a +// QuarantineFileResult. +// +// Typical return codes from IAttachmentExecute::Save(): +// S_OK : The file was okay. If any viruses were found, they were cleaned. +// E_FAIL : Virus infected. +// INET_E_SECURITY_PROBLEM : The file was blocked due to security policy. +// +// Any other return value indicates an unexpected error during the scan. +QuarantineFileResult FailedSaveResultToQuarantineResult(HRESULT result) { + switch (result) { + case INET_E_SECURITY_PROBLEM: // 0x800c000e + // This is returned if the download was blocked due to security + // restrictions. E.g. if the source URL was in the Restricted Sites zone + // and downloads are blocked on that zone, then the download would be + // deleted and this error code is returned. + return QuarantineFileResult::BLOCKED_BY_POLICY; + + case E_FAIL: // 0x80004005 + // Returned if an anti-virus product reports an infection in the + // downloaded file during IAE::Save(). + return QuarantineFileResult::VIRUS_INFECTED; + + default: + // Any other error that occurs during IAttachmentExecute::Save() likely + // indicates a problem with the security check, but not necessarily the + // download. This also includes cases where SUCCEEDED(result) is true. In + // the latter case we are likely dealing with a situation where the file + // is missing after a successful scan. See http://crbug.com/153212. + return QuarantineFileResult::SECURITY_CHECK_FAILED; + } +} + // Invokes IAttachmentExecute::Save on CLSID_AttachmentServices to validate the // downloaded file. The call may scan the file for viruses and if necessary, // annotate it with evidence. As a result of the validation, the file may be @@ -99,19 +132,12 @@ // // IAE::Save() will delete the file if it was found to be blocked by local // security policy or if it was found to be infected. The call may also delete -// the file due to other failures (http://crbug.com/153212). A failure code will -// be returned in these cases. +// the file due to other failures (http://crbug.com/153212). In these cases, +// |result| will contain the failure code. // // The return value is |false| iff the function fails to invoke // IAttachmentExecute::Save(). If the function returns |true|, then the result -// of invoking IAttachmentExecute::Save() is stored in |save_result|. -// -// Typical |save_result| values: -// S_OK : The file was okay. If any viruses were found, they were cleaned. -// E_FAIL : Virus infected. -// INET_E_SECURITY_PROBLEM : The file was blocked due to security policy. -// -// Any other return value indicates an unexpected error during the scan. +// of invoking IAttachmentExecute::Save() is stored in |result|. // // |full_path| : is the path to the downloaded file. This should be the final // path of the download. Must be present. @@ -121,16 +147,15 @@ // will not be set. // |client_guid|: the GUID to be set in the IAttachmentExecute client slot. // Used to identify the app to the system AV function. -// |save_result|: Receives the result of invoking IAttachmentExecute::Save(). +// |result|: Receives the result of invoking IAttachmentExecute::Save(). bool InvokeAttachmentServices(const base::FilePath& full_path, const GURL& source_url, const GURL& referrer_url, const GUID& client_guid, - HRESULT* save_result) { + QuarantineFileResult* result) { Microsoft::WRL::ComPtr<IAttachmentExecute> attachment_services; HRESULT hr = ::CoCreateInstance(CLSID_AttachmentServices, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&attachment_services)); - *save_result = S_OK; if (FAILED(hr)) { // The thread must have COM initialized. @@ -175,41 +200,32 @@ return false; } + HRESULT save_result = S_OK; { // This method has been known to take longer than 10 seconds in some // instances. SCOPED_UMA_HISTOGRAM_LONG_TIMER("Download.AttachmentServices.Duration"); - *save_result = attachment_services->Save(); + save_result = attachment_services->Save(); } + + // If the download file is missing after the call, then treat this as an + // interrupted download. + // + // If IAttachmentExecute::Save() failed, but the downloaded file is still + // around, then don't interrupt the download. Attachment Execution Services + // deletes the submitted file if the downloaded file is blocked by policy or + // if it was found to be infected. + // + // If the file is still there, then the error could be due to Windows + // Attachment Services not being available or some other error during the AES + // invocation. In either case, we don't surface the error to the user. + *result = base::PathExists(full_path) + ? QuarantineFileResult::OK + : FailedSaveResultToQuarantineResult(save_result); + return true; } -// Maps a return code from an unsuccessful IAttachmentExecute::Save() call to a -// QuarantineFileResult. -QuarantineFileResult FailedSaveResultToQuarantineResult(HRESULT result) { - switch (result) { - case INET_E_SECURITY_PROBLEM: // 0x800c000e - // This is returned if the download was blocked due to security - // restrictions. E.g. if the source URL was in the Restricted Sites zone - // and downloads are blocked on that zone, then the download would be - // deleted and this error code is returned. - return QuarantineFileResult::BLOCKED_BY_POLICY; - - case E_FAIL: // 0x80004005 - // Returned if an anti-virus product reports an infection in the - // downloaded file during IAE::Save(). - return QuarantineFileResult::VIRUS_INFECTED; - - default: - // Any other error that occurs during IAttachmentExecute::Save() likely - // indicates a problem with the security check, but not necessarily the - // download. This also includes cases where SUCCEEDED(result) is true. In - // the latter case we are likely dealing with a situation where the file - // is missing after a successful scan. See http://crbug.com/153212. - return QuarantineFileResult::SECURITY_CHECK_FAILED; - } -} - } // namespace QuarantineFileResult QuarantineFile(const base::FilePath& file, @@ -238,8 +254,6 @@ return SetInternetZoneIdentifierDirectly(file, source_url, referrer_url); } - HRESULT save_result = S_OK; - // Check if the attachment services should be invoked based on the experiment // state. Not invoking the attachment services means that the Zone Identifier // will always be set to 3 (Internet), regardless of URL zones configurations. @@ -252,27 +266,14 @@ base::IsMachineExternallyManaged() || base::FeatureList::IsEnabled(kInvokeAttachmentServices); - bool attachment_services_available = - should_invoke_attachment_services && + QuarantineFileResult attachment_services_result = QuarantineFileResult::OK; + if (should_invoke_attachment_services && InvokeAttachmentServices(file, source_url, referrer_url, guid, - &save_result); - if (!attachment_services_available) - return SetInternetZoneIdentifierDirectly(file, source_url, referrer_url); + &attachment_services_result)) { + return attachment_services_result; + } - // If the download file is missing after the call, then treat this as an - // interrupted download. - // - // If InvokeAttachmentServices() failed, but the downloaded file is still - // around, then don't interrupt the download. Attachment Execution Services - // deletes the submitted file if the downloaded file is blocked by policy or - // if it was found to be infected. - // - // If the file is still there, then the error could be due to Windows - // Attachment Services not being available or some other error during the AES - // invocation. In either case, we don't surface the error to the user. - if (!base::PathExists(file)) - return FailedSaveResultToQuarantineResult(save_result); - return QuarantineFileResult::OK; + return SetInternetZoneIdentifierDirectly(file, source_url, referrer_url); } } // namespace download
diff --git a/components/leveldb_proto/internal/proto_database_impl.h b/components/leveldb_proto/internal/proto_database_impl.h index 7759022..d80bd8c 100644 --- a/components/leveldb_proto/internal/proto_database_impl.h +++ b/components/leveldb_proto/internal/proto_database_impl.h
@@ -180,15 +180,15 @@ typename T, std::enable_if_t<std::is_base_of<google::protobuf::MessageLite, T>::value>* = nullptr> -std::string SerializeAsString(const T& entry) { - return entry.SerializeAsString(); +std::string SerializeAsString(T* entry) { + return entry->SerializeAsString(); } template <typename P, typename T, std::enable_if_t<!std::is_base_of<google::protobuf::MessageLite, T>::value>* = nullptr> -std::string SerializeAsString(const T& entry) { +std::string SerializeAsString(T* entry) { P proto; DataToProto(entry, &proto); return proto.SerializeAsString(); @@ -221,7 +221,7 @@ if (!ParseToProto<P>(serialized_entry, &proto)) return false; - ProtoToData(proto, entry); + ProtoToData(&proto, entry); return true; } @@ -237,8 +237,8 @@ Callbacks::UpdateCallback callback) { // Serialize the values from Proto to string before passing on to database. auto pairs_to_save = std::make_unique<KeyValueVector>(); - for (const auto& pair : *entries_to_save) { - auto serialized = SerializeAsString<P, T>(pair.second); + for (auto& pair : *entries_to_save) { + auto serialized = SerializeAsString<P, T>(&pair.second); pairs_to_save->push_back(std::make_pair(pair.first, serialized)); } @@ -258,8 +258,8 @@ Callbacks::UpdateCallback callback) { // Serialize the values from Proto to string before passing on to database. auto pairs_to_save = std::make_unique<KeyValueVector>(); - for (const auto& pair : *entries_to_save) { - auto serialized = SerializeAsString<P, T>(pair.second); + for (auto& pair : *entries_to_save) { + auto serialized = SerializeAsString<P, T>(&pair.second); pairs_to_save->push_back(std::make_pair(pair.first, serialized)); }
diff --git a/components/leveldb_proto/internal/proto_database_impl_unittest.cc b/components/leveldb_proto/internal/proto_database_impl_unittest.cc index 8c026233..68d35b6 100644 --- a/components/leveldb_proto/internal/proto_database_impl_unittest.cc +++ b/components/leveldb_proto/internal/proto_database_impl_unittest.cc
@@ -37,10 +37,8 @@ // The methods below are convenience methods to have a similar API as protocol // buffers for the test framework. This is NOT required for uses of client // structs. - const std::string& id() const { return id_; } - void set_id(const std::string& id) { id_ = id; } - const std::string& data() const { return data_; } - void set_data(const std::string& data) { data_ = data; } + std::string id() const { return id_; } + std::string data() const { return data_; } std::string id_; std::string data_; @@ -61,18 +59,18 @@ const std::string& data, ClientStruct* as_struct) { // Ensure the DB key, the id-field and data-field are all unique values. - as_struct->set_id(key + key); - as_struct->set_data(key + key + key); + as_struct->id_ = key + key; + as_struct->data_ = key + key + key; } -void DataToProto(const ClientStruct& data, TestProto* proto) { - proto->set_id(data.id()); - proto->set_data(data.data()); +void DataToProto(ClientStruct* data, TestProto* proto) { + proto->mutable_id()->swap(data->id_); + proto->mutable_data()->swap(data->data_); } -void ProtoToData(const TestProto& proto, ClientStruct* data) { - data->set_id(proto.id()); - data->set_data(proto.data()); +void ProtoToData(TestProto* proto, ClientStruct* data) { + proto->mutable_id()->swap(data->id_); + proto->mutable_data()->swap(data->data_); } } // namespace
diff --git a/components/leveldb_proto/testing/fake_db.h b/components/leveldb_proto/testing/fake_db.h index 85a699b..4f6fa10 100644 --- a/components/leveldb_proto/testing/fake_db.h +++ b/components/leveldb_proto/testing/fake_db.h
@@ -139,15 +139,15 @@ typename T, std::enable_if_t<std::is_base_of<google::protobuf::MessageLite, T>::value>* = nullptr> -void DataToProtoWrap(const T& data, P* proto) { - *proto = data; +void DataToProtoWrap(T* data, P* proto) { + proto->Swap(data); } template <typename P, typename T, std::enable_if_t<!std::is_base_of<google::protobuf::MessageLite, T>::value>* = nullptr> -void DataToProtoWrap(const T& data, P* proto) { +void DataToProtoWrap(T* data, P* proto) { DataToProto(data, proto); } @@ -155,16 +155,17 @@ typename T, std::enable_if_t<std::is_base_of<google::protobuf::MessageLite, T>::value>* = nullptr> -void ProtoToDataWrap(const P& proto, T* copy) { - *copy = proto; +void ProtoToDataWrap(const P& proto, T* data) { + *data = proto; } template <typename P, typename T, std::enable_if_t<!std::is_base_of<google::protobuf::MessageLite, T>::value>* = nullptr> -void ProtoToDataWrap(const P& proto, T* copy) { - ProtoToData(proto, copy); +void ProtoToDataWrap(const P& proto, T* data) { + P copy = proto; + ProtoToData(©, data); } } // namespace @@ -208,8 +209,8 @@ std::unique_ptr<typename ProtoDatabase<T>::KeyEntryVector> entries_to_save, std::unique_ptr<std::vector<std::string>> keys_to_remove, Callbacks::UpdateCallback callback) { - for (const auto& pair : *entries_to_save) - DataToProtoWrap(pair.second, &(*db_)[pair.first]); + for (auto& pair : *entries_to_save) + DataToProtoWrap(&pair.second, &(*db_)[pair.first]); for (const auto& key : *keys_to_remove) db_->erase(key); @@ -223,7 +224,7 @@ const KeyFilter& delete_key_filter, Callbacks::UpdateCallback callback) { for (auto& pair : *entries_to_save) - DataToProtoWrap(pair.second, &(*db_)[pair.first]); + DataToProtoWrap(&pair.second, &(*db_)[pair.first]); auto it = db_->begin(); while (it != db_->end()) {
diff --git a/components/offline_items_collection/core/BUILD.gn b/components/offline_items_collection/core/BUILD.gn index 917698f4..2a9bc1d 100644 --- a/components/offline_items_collection/core/BUILD.gn +++ b/components/offline_items_collection/core/BUILD.gn
@@ -9,6 +9,7 @@ static_library("core") { sources = [ + "fail_state.cc", "fail_state.h", "filtered_offline_item_observer.cc", "filtered_offline_item_observer.h",
diff --git a/components/offline_items_collection/core/fail_state.cc b/components/offline_items_collection/core/fail_state.cc new file mode 100644 index 0000000..aa0caa1 --- /dev/null +++ b/components/offline_items_collection/core/fail_state.cc
@@ -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. + +#include "components/offline_items_collection/core/fail_state.h" + +namespace offline_items_collection { + +bool ToFailState(int value, FailState* fail_state) { + switch (static_cast<FailState>(value)) { + case FailState::NO_FAILURE: + case FailState::CANNOT_DOWNLOAD: + case FailState::NETWORK_INSTABILITY: + case FailState::FILE_FAILED: + case FailState::FILE_ACCESS_DENIED: + case FailState::FILE_NO_SPACE: + case FailState::FILE_NAME_TOO_LONG: + case FailState::FILE_TOO_LARGE: + case FailState::FILE_VIRUS_INFECTED: + case FailState::FILE_TRANSIENT_ERROR: + case FailState::FILE_BLOCKED: + case FailState::FILE_SECURITY_CHECK_FAILED: + case FailState::FILE_TOO_SHORT: + case FailState::FILE_HASH_MISMATCH: + case FailState::FILE_SAME_AS_SOURCE: + case FailState::NETWORK_FAILED: + case FailState::NETWORK_TIMEOUT: + case FailState::NETWORK_DISCONNECTED: + case FailState::NETWORK_SERVER_DOWN: + case FailState::NETWORK_INVALID_REQUEST: + case FailState::SERVER_FAILED: + case FailState::SERVER_NO_RANGE: + case FailState::SERVER_BAD_CONTENT: + case FailState::SERVER_UNAUTHORIZED: + case FailState::SERVER_CERT_PROBLEM: + case FailState::SERVER_FORBIDDEN: + case FailState::SERVER_UNREACHABLE: + case FailState::SERVER_CONTENT_LENGTH_MISMATCH: + case FailState::SERVER_CROSS_ORIGIN_REDIRECT: + case FailState::USER_CANCELED: + case FailState::USER_SHUTDOWN: + case FailState::CRASH: + *fail_state = static_cast<FailState>(value); + return true; + } + return false; +} + +} // namespace offline_items_collection
diff --git a/components/offline_items_collection/core/fail_state.h b/components/offline_items_collection/core/fail_state.h index 606a2b3..f1547b40 100644 --- a/components/offline_items_collection/core/fail_state.h +++ b/components/offline_items_collection/core/fail_state.h
@@ -5,8 +5,12 @@ #ifndef COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_FAIL_STATE_H_ #define COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_FAIL_STATE_H_ +#include <iosfwd> + namespace offline_items_collection { +// Warning: These enumeration values are saved to a database, enumeration values +// should not be changed. // A Java counterpart will be generated for this enum. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.offline_items_collection enum class FailState { @@ -126,6 +130,8 @@ CRASH, }; +bool ToFailState(int value, FailState* fail_state); + // Implemented for testing only. See test_support/offline_item_test_support.cc. std::ostream& operator<<(std::ostream& os, FailState state);
diff --git a/components/offline_pages/core/background/request_queue_store.cc b/components/offline_pages/core/background/request_queue_store.cc index 9d74f45..c8ecd19 100644 --- a/components/offline_pages/core/background/request_queue_store.cc +++ b/components/offline_pages/core/background/request_queue_store.cc
@@ -178,6 +178,10 @@ return transaction.Commit(); } +// Enum conversion code. Database corruption is possible, so make sure enum +// values are in the domain. Because corruption is rare, there is not robust +// error handling. + SavePageRequest::AutoFetchNotificationState AutoFetchNotificationStateFromInt( int value) { switch (static_cast<SavePageRequest::AutoFetchNotificationState>(value)) { @@ -185,9 +189,30 @@ case SavePageRequest::AutoFetchNotificationState::kShown: return static_cast<SavePageRequest::AutoFetchNotificationState>(value); } + DLOG(ERROR) << "Invalid AutoFetchNotificationState value: " << value; return SavePageRequest::AutoFetchNotificationState::kUnknown; } +SavePageRequest::RequestState ToRequestState(int value) { + switch (static_cast<SavePageRequest::RequestState>(value)) { + case SavePageRequest::RequestState::AVAILABLE: + case SavePageRequest::RequestState::PAUSED: + case SavePageRequest::RequestState::OFFLINING: + return static_cast<SavePageRequest::RequestState>(value); + } + DLOG(ERROR) << "Invalid RequestState value: " << value; + return SavePageRequest::RequestState::AVAILABLE; +} + +offline_items_collection::FailState ToFailState(int value) { + offline_items_collection::FailState state = FailState::NO_FAILURE; + if (!offline_items_collection::ToFailState(value, &state)) { + DLOG(ERROR) << "Invalid FailState: " << value; + } + + return state; +} + // Create a save page request from the first row of an SQL result. The result // must have the exact columns from the |REQUEST_QUEUE_FIELDS| macro. std::unique_ptr<SavePageRequest> MakeSavePageRequest( @@ -200,7 +225,7 @@ const int64_t started_attempt_count = statement.ColumnInt64(4); const int64_t completed_attempt_count = statement.ColumnInt64(5); const SavePageRequest::RequestState state = - static_cast<SavePageRequest::RequestState>(statement.ColumnInt64(6)); + ToRequestState(statement.ColumnInt64(6)); const GURL url(statement.ColumnString(7)); const ClientId client_id(statement.ColumnString(8), statement.ColumnString(9)); @@ -221,7 +246,7 @@ request->set_request_state(state); request->set_original_url(std::move(original_url)); request->set_request_origin(std::move(request_origin)); - request->set_fail_state(static_cast<FailState>(statement.ColumnInt64(12))); + request->set_fail_state(ToFailState(statement.ColumnInt64(12))); request->set_auto_fetch_notification_state( AutoFetchNotificationStateFromInt(statement.ColumnInt(13))); return request;
diff --git a/components/offline_pages/core/background/save_page_request.h b/components/offline_pages/core/background/save_page_request.h index 77f02c0..9e42ce5 100644 --- a/components/offline_pages/core/background/save_page_request.h +++ b/components/offline_pages/core/background/save_page_request.h
@@ -23,7 +23,7 @@ class SavePageRequest { public: // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.offlinepages - enum class RequestState { + enum class RequestState : int { AVAILABLE = 0, // Request can be scheduled when preconditions are met. PAUSED = 1, // Request is not available until it is unpaused. OFFLINING = 2, // Request is actively offlining.
diff --git a/components/offline_pages/core/prefetch/prefetch_types.cc b/components/offline_pages/core/prefetch/prefetch_types.cc index e71c50ad..2b4ca22 100644 --- a/components/offline_pages/core/prefetch/prefetch_types.cc +++ b/components/offline_pages/core/prefetch/prefetch_types.cc
@@ -115,6 +115,8 @@ return "STALE_AT_UNKNOWN"; case PrefetchItemErrorCode::STUCK: return "STUCK"; + case PrefetchItemErrorCode::INVALID_ITEM: + return "INVALID_ITEM"; case PrefetchItemErrorCode::GET_OPERATION_MAX_ATTEMPTS_REACHED: return "GET_OPERATION_MAX_ATTEMPTS_REACHED"; case PrefetchItemErrorCode:: @@ -215,6 +217,35 @@ return base::nullopt; } +base::Optional<PrefetchItemErrorCode> ToPrefetchItemErrorCode(int value) { + switch (static_cast<PrefetchItemErrorCode>(value)) { + case PrefetchItemErrorCode::SUCCESS: + case PrefetchItemErrorCode::TOO_MANY_NEW_URLS: + case PrefetchItemErrorCode::DOWNLOAD_ERROR: + case PrefetchItemErrorCode::IMPORT_ERROR: + case PrefetchItemErrorCode::ARCHIVING_FAILED: + case PrefetchItemErrorCode::ARCHIVING_LIMIT_EXCEEDED: + case PrefetchItemErrorCode::STALE_AT_NEW_REQUEST: + case PrefetchItemErrorCode::STALE_AT_AWAITING_GCM: + case PrefetchItemErrorCode::STALE_AT_RECEIVED_GCM: + case PrefetchItemErrorCode::STALE_AT_RECEIVED_BUNDLE: + case PrefetchItemErrorCode::STALE_AT_DOWNLOADING: + case PrefetchItemErrorCode::STALE_AT_IMPORTING: + case PrefetchItemErrorCode::STALE_AT_UNKNOWN: + case PrefetchItemErrorCode::STUCK: + case PrefetchItemErrorCode::INVALID_ITEM: + case PrefetchItemErrorCode::GET_OPERATION_MAX_ATTEMPTS_REACHED: + case PrefetchItemErrorCode:: + GENERATE_PAGE_BUNDLE_REQUEST_MAX_ATTEMPTS_REACHED: + case PrefetchItemErrorCode::DOWNLOAD_MAX_ATTEMPTS_REACHED: + case PrefetchItemErrorCode::MAXIMUM_CLOCK_BACKWARD_SKEW_EXCEEDED: + case PrefetchItemErrorCode::IMPORT_LOST: + case PrefetchItemErrorCode::SUGGESTION_INVALIDATED: + return static_cast<PrefetchItemErrorCode>(value); + } + return base::nullopt; +} + std::ostream& operator<<(std::ostream& out, PrefetchBackgroundTaskRescheduleType value) { return out << PrefetchEnumToString(value);
diff --git a/components/offline_pages/core/prefetch/prefetch_types.h b/components/offline_pages/core/prefetch/prefetch_types.h index a4c425f2..2816518 100644 --- a/components/offline_pages/core/prefetch/prefetch_types.h +++ b/components/offline_pages/core/prefetch/prefetch_types.h
@@ -159,7 +159,7 @@ // Changes to this enum must be reflected in the respective metrics enum named // OflinePrefetchItemErrorCode in enums.xml. Use the exact same integer value // for each mirrored entry. -enum class PrefetchItemErrorCode { +enum class PrefetchItemErrorCode : int { // The entry had gone through the pipeline and successfully completed // prefetching. Explicitly setting to 0 as that is the default value for the // respective SQLite column. @@ -192,6 +192,8 @@ // The item was terminated because it remained in the pipeline for more than // 7 days. STUCK = 1150, + // The item had some invalid data, probably due to database corruption. + INVALID_ITEM = 1175, // Exceeded maximum retries for get operation request. GET_OPERATION_MAX_ATTEMPTS_REACHED = 1200, // Exceeded maximum retries limit for generate page bundle request. @@ -210,6 +212,8 @@ kMaxValue = SUGGESTION_INVALIDATED }; +base::Optional<PrefetchItemErrorCode> ToPrefetchItemErrorCode(int value); + // Callback invoked upon completion of a prefetch request. using PrefetchRequestFinishedCallback = base::OnceCallback<void(PrefetchRequestStatus status,
diff --git a/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc b/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc index 27c2068..45fd12f 100644 --- a/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc +++ b/components/offline_pages/core/prefetch/store/prefetch_store_test_util.cc
@@ -115,7 +115,11 @@ item.archive_body_length = statement.ColumnInt64(5); item.creation_time = store_utils::FromDatabaseTime(statement.ColumnInt64(6)); item.freshness_time = store_utils::FromDatabaseTime(statement.ColumnInt64(7)); - item.error_code = static_cast<PrefetchItemErrorCode>(statement.ColumnInt(8)); + base::Optional<PrefetchItemErrorCode> error_code = + ToPrefetchItemErrorCode(statement.ColumnInt(8)); + if (!error_code) + return base::nullopt; + item.error_code = error_code.value(); item.guid = statement.ColumnString(9); item.client_id.name_space = statement.ColumnString(10); item.client_id.id = statement.ColumnString(11);
diff --git a/components/offline_pages/core/prefetch/tasks/metrics_finalization_task.cc b/components/offline_pages/core/prefetch/tasks/metrics_finalization_task.cc index 413d099..a93e27b 100644 --- a/components/offline_pages/core/prefetch/tasks/metrics_finalization_task.cc +++ b/components/offline_pages/core/prefetch/tasks/metrics_finalization_task.cc
@@ -67,6 +67,10 @@ std::vector<PrefetchItemStats> urls; while (statement.Step()) { + PrefetchItemErrorCode error_code = + ToPrefetchItemErrorCode(statement.ColumnInt(6)) + .value_or(PrefetchItemErrorCode::INVALID_ITEM); + urls.emplace_back(statement.ColumnInt64(0), // offline_id statement.ColumnInt(1), // generate_bundle_attempts statement.ColumnInt(2), // get_operation_attempts @@ -74,9 +78,8 @@ statement.ColumnInt64(4), // archive_body_length store_utils::FromDatabaseTime( statement.ColumnInt64(5)), // creation_time - static_cast<PrefetchItemErrorCode>( - statement.ColumnInt(6)), // error_code - statement.ColumnInt64(7)); // file_size + error_code, // error_code + statement.ColumnInt64(7)); // file_size } return urls;
diff --git a/components/offline_pages/core/prefetch/tasks/stale_entry_finalizer_task.cc b/components/offline_pages/core/prefetch/tasks/stale_entry_finalizer_task.cc index e2078f2..fc31faf 100644 --- a/components/offline_pages/core/prefetch/tasks/stale_entry_finalizer_task.cc +++ b/components/offline_pages/core/prefetch/tasks/stale_entry_finalizer_task.cc
@@ -177,8 +177,11 @@ statement.BindInt64(2, static_cast<int>(PrefetchItemState::ZOMBIE)); while (statement.Step()) { - base::UmaHistogramSparse("OfflinePages.Prefetching.StuckItemState", - statement.ColumnInt(0)); + int state_int = statement.ColumnInt(0); + if (ToPrefetchItemState(state_int)) { // Only report valid enum values. + base::UmaHistogramSparse("OfflinePages.Prefetching.StuckItemState", + state_int); + } } } // Finalize.
diff --git a/components/password_manager/core/browser/sync/password_syncable_service.cc b/components/password_manager/core/browser/sync/password_syncable_service.cc index 56f8ac8..915a401 100644 --- a/components/password_manager/core/browser/sync/password_syncable_service.cc +++ b/components/password_manager/core/browser/sync/password_syncable_service.cc
@@ -340,7 +340,7 @@ // TODO(wychen): enum uma should be strongly typed. crbug.com/661401 UMA_HISTOGRAM_ENUMERATION("Sync.LocalDataFailedToLoad", ModelTypeToHistogramInt(syncer::PASSWORDS), - static_cast<int>(syncer::MODEL_TYPE_COUNT)); + static_cast<int>(syncer::ModelType::NUM_ENTRIES)); return false; } password_entries->resize(autofillable_entries.size() +
diff --git a/components/previews/content/previews_hints.cc b/components/previews/content/previews_hints.cc index 4b4e021..005ad55 100644 --- a/components/previews/content/previews_hints.cc +++ b/components/previews/content/previews_hints.cc
@@ -347,10 +347,11 @@ } if (static_cast<int>(bloom_filter_proto.num_bits()) > previews::params:: - LitePageRedirectPreviewMaxServerBlacklistByteSize() / + LitePageRedirectPreviewMaxServerBlacklistByteSize() * 8) { DLOG(ERROR) << "Bloom filter data exceeds maximum size of " - << previews::params::PreviewServerLoadshedMaxSeconds() + << previews::params:: + LitePageRedirectPreviewMaxServerBlacklistByteSize() << " bytes"; RecordOptimizationFilterStatus( previews_type.value(),
diff --git a/components/safe_browsing/browser/mojo_safe_browsing_impl.cc b/components/safe_browsing/browser/mojo_safe_browsing_impl.cc index 75472f0..0b39040 100644 --- a/components/safe_browsing/browser/mojo_safe_browsing_impl.cc +++ b/components/safe_browsing/browser/mojo_safe_browsing_impl.cc
@@ -8,6 +8,7 @@ #include <vector> #include "base/bind.h" +#include "base/supports_user_data.h" #include "components/safe_browsing/browser/safe_browsing_url_checker_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" @@ -56,6 +57,22 @@ Callback callback_; }; +// UserData object that owns MojoSafeBrowsingImpl. This is used rather than +// having MojoSafeBrowsingImpl directly extend base::SupportsUserData::Data to +// avoid naming conflicts between Data::Clone() and +// mojom::SafeBrowsing::Clone(). +class SafeBrowserUserData : public base::SupportsUserData::Data { + public: + explicit SafeBrowserUserData(std::unique_ptr<MojoSafeBrowsingImpl> impl) + : impl_(std::move(impl)) {} + ~SafeBrowserUserData() override = default; + + private: + std::unique_ptr<MojoSafeBrowsingImpl> impl_; + + DISALLOW_COPY_AND_ASSIGN(SafeBrowserUserData); +}; + } // namespace MojoSafeBrowsingImpl::MojoSafeBrowsingImpl( @@ -95,11 +112,11 @@ std::move(delegate), render_process_id, resource_context)); impl->Clone(std::move(request)); - // Need to store the value of |impl.get()| in a temp variable instead of - // getting the value on the same line as |std::move(impl)|, because the - // evalution order is unspecified. - const void* key = impl.get(); - resource_context->SetUserData(key, std::move(impl)); + MojoSafeBrowsingImpl* raw_impl = impl.get(); + std::unique_ptr<SafeBrowserUserData> user_data = + std::make_unique<SafeBrowserUserData>(std::move(impl)); + raw_impl->user_data_key_ = user_data.get(); + resource_context->SetUserData(raw_impl->user_data_key_, std::move(user_data)); } void MojoSafeBrowsingImpl::CreateCheckerAndCheck( @@ -150,7 +167,7 @@ void MojoSafeBrowsingImpl::OnConnectionError() { if (bindings_.empty()) { - resource_context_->RemoveUserData(this); + resource_context_->RemoveUserData(user_data_key_); // This object is destroyed. } }
diff --git a/components/safe_browsing/browser/mojo_safe_browsing_impl.h b/components/safe_browsing/browser/mojo_safe_browsing_impl.h index e627f1d..7a670b7 100644 --- a/components/safe_browsing/browser/mojo_safe_browsing_impl.h +++ b/components/safe_browsing/browser/mojo_safe_browsing_impl.h
@@ -7,7 +7,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/supports_user_data.h" #include "components/safe_browsing/browser/url_checker_delegate.h" #include "components/safe_browsing/common/safe_browsing.mojom.h" #include "ipc/ipc_message.h" @@ -23,8 +22,7 @@ // SafeBrowsing URL checks. // A MojoSafeBrowsingImpl instance is destructed when the Mojo message pipe is // disconnected or |resource_context_| is destructed. -class MojoSafeBrowsingImpl : public mojom::SafeBrowsing, - public base::SupportsUserData::Data { +class MojoSafeBrowsingImpl : public mojom::SafeBrowsing { public: ~MojoSafeBrowsingImpl() override; @@ -54,6 +52,10 @@ void OnConnectionError(); + // This is an instance of SafeBrowserUserData that is set as user-data on + // |resource_context_|. SafeBrowserUserData owns |this|. + const void* user_data_key_ = nullptr; + mojo::BindingSet<mojom::SafeBrowsing> bindings_; scoped_refptr<UrlCheckerDelegate> delegate_; int render_process_id_ = MSG_ROUTING_NONE;
diff --git a/components/safe_browsing/db/BUILD.gn b/components/safe_browsing/db/BUILD.gn index acda1f22..7cf0548 100644 --- a/components/safe_browsing/db/BUILD.gn +++ b/components/safe_browsing/db/BUILD.gn
@@ -31,7 +31,6 @@ ":hit_report", ":safebrowsing_proto", ":util", - ":v4_feature_list", # Used by SafeBrowsingService "//components/safe_browsing/common:safe_browsing_prefs", ] } @@ -135,17 +134,6 @@ ] } -static_library("v4_feature_list") { - sources = [ - "v4_feature_list.cc", - "v4_feature_list.h", - ] - deps = [ - "//base", - "//components/safe_browsing:features", - ] -} - static_library("v4_get_hash_protocol_manager") { sources = [ "v4_get_hash_protocol_manager.cc", @@ -176,7 +164,6 @@ ":hit_report", ":safebrowsing_proto", ":v4_database", - ":v4_feature_list", ":v4_get_hash_protocol_manager", ":v4_protocol_manager_util", ":v4_update_protocol_manager",
diff --git a/components/safe_browsing/db/v4_feature_list.cc b/components/safe_browsing/db/v4_feature_list.cc deleted file mode 100644 index 2213692..0000000 --- a/components/safe_browsing/db/v4_feature_list.cc +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/safe_browsing/db/v4_feature_list.h" - -#include "base/feature_list.h" -#include "components/safe_browsing/features.h" - -namespace safe_browsing { - -namespace V4FeatureList { - -V4UsageStatus GetV4UsageStatus() { -#if defined(SAFE_BROWSING_DB_LOCAL) - return V4UsageStatus::V4_ONLY; -#else - return V4UsageStatus::V4_DISABLED; -#endif -} - -} // namespace V4FeatureList - -} // namespace safe_browsing
diff --git a/components/safe_browsing/db/v4_feature_list.h b/components/safe_browsing/db/v4_feature_list.h deleted file mode 100644 index 5d7079a..0000000 --- a/components/safe_browsing/db/v4_feature_list.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_SAFE_BROWSING_DB_V4_FEATURE_LIST_H_ -#define COMPONENTS_SAFE_BROWSING_DB_V4_FEATURE_LIST_H_ - -namespace safe_browsing { - -// Exposes methods to check whether a particular feature has been enabled -// through Finch. -namespace V4FeatureList { - -enum class V4UsageStatus { - // The V4 database manager is not even instantiated i.e. is diabled. All - // SafeBrowsing operations use PVer3 code. - V4_DISABLED, - - // The V4 database manager is instantiated, and performs background updates, - // but all SafeBrowsing verdicts are returned using the PVer3 database. - V4_INSTANTIATED, - - // Only the V4 database manager is instantiated, PVer3 database manager is - // not. All SafeBrowsing verdicts are returned using PVer4 database. - V4_ONLY -}; - -V4UsageStatus GetV4UsageStatus(); - -} // namespace V4FeatureList - -} // namespace safe_browsing - -#endif // COMPONENTS_SAFE_BROWSING_DB_V4_FEATURE_LIST_H_
diff --git a/components/safe_browsing/db/v4_local_database_manager.cc b/components/safe_browsing/db/v4_local_database_manager.cc index 936689b..d40788f 100644 --- a/components/safe_browsing/db/v4_local_database_manager.cc +++ b/components/safe_browsing/db/v4_local_database_manager.cc
@@ -18,7 +18,6 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/task/post_task.h" -#include "components/safe_browsing/db/v4_feature_list.h" #include "components/safe_browsing/db/v4_protocol_manager_util.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h"
diff --git a/components/safe_browsing/web_ui/safe_browsing_ui.cc b/components/safe_browsing/web_ui/safe_browsing_ui.cc index 340eca0..60f878fd 100644 --- a/components/safe_browsing/web_ui/safe_browsing_ui.cc +++ b/components/safe_browsing/web_ui/safe_browsing_ui.cc
@@ -59,13 +59,12 @@ // static bool WebUIInfoSingleton::HasListener() { - return GetInstance()->has_test_listener_ || - !GetInstance()->webui_instances_.empty(); + return !GetInstance()->webui_instances_.empty(); } void WebUIInfoSingleton::AddToClientDownloadRequestsSent( std::unique_ptr<ClientDownloadRequest> client_download_request) { - if (!HasListener()) + if (webui_instances_.empty()) return; for (auto* webui_listener : webui_instances_) @@ -81,7 +80,7 @@ void WebUIInfoSingleton::AddToClientDownloadResponsesReceived( std::unique_ptr<ClientDownloadResponse> client_download_response) { - if (!HasListener()) + if (webui_instances_.empty()) return; for (auto* webui_listener : webui_instances_) @@ -98,7 +97,7 @@ void WebUIInfoSingleton::AddToCSBRRsSent( std::unique_ptr<ClientSafeBrowsingReportRequest> csbrr) { - if (!HasListener()) + if (webui_instances_.empty()) return; for (auto* webui_listener : webui_instances_) @@ -113,7 +112,7 @@ void WebUIInfoSingleton::AddToPGEvents( const sync_pb::UserEventSpecifics& event) { - if (!HasListener()) + if (webui_instances_.empty()) return; for (auto* webui_listener : webui_instances_) @@ -128,7 +127,7 @@ int WebUIInfoSingleton::AddToPGPings( const LoginReputationClientRequest& request) { - if (!HasListener()) + if (webui_instances_.empty()) return -1; for (auto* webui_listener : webui_instances_) @@ -142,7 +141,7 @@ void WebUIInfoSingleton::AddToPGResponses( int token, const LoginReputationClientResponse& response) { - if (!HasListener()) + if (webui_instances_.empty()) return; for (auto* webui_listener : webui_instances_) @@ -157,7 +156,7 @@ } void WebUIInfoSingleton::LogMessage(const std::string& message) { - if (!HasListener()) + if (webui_instances_.empty()) return; base::Time timestamp = base::Time::Now(); @@ -177,7 +176,7 @@ void WebUIInfoSingleton::UnregisterWebUIInstance(SafeBrowsingUIHandler* webui) { base::Erase(webui_instances_, webui); - if (!HasListener()) { + if (webui_instances_.empty()) { ClearCSBRRsSent(); ClearClientDownloadRequestsSent(); ClearClientDownloadResponsesReceived();
diff --git a/components/safe_browsing/web_ui/safe_browsing_ui.h b/components/safe_browsing/web_ui/safe_browsing_ui.h index 23d4515..dcd3e82 100644 --- a/components/safe_browsing/web_ui/safe_browsing_ui.h +++ b/components/safe_browsing/web_ui/safe_browsing_ui.h
@@ -251,8 +251,6 @@ return log_messages_; } - void AddListenerForTesting() { has_test_listener_ = true; } - private: WebUIInfoSingleton(); ~WebUIInfoSingleton(); @@ -303,9 +301,6 @@ // The current referrer chain provider, if any. Can be nullptr. ReferrerChainProvider* referrer_chain_provider_ = nullptr; - // Whether there is a test listener. - bool has_test_listener_ = false; - DISALLOW_COPY_AND_ASSIGN(WebUIInfoSingleton); };
diff --git a/components/sessions/BUILD.gn b/components/sessions/BUILD.gn index 78c52453..84d9062 100644 --- a/components/sessions/BUILD.gn +++ b/components/sessions/BUILD.gn
@@ -59,6 +59,7 @@ deps = [ "//base", + "//ios/web/common", ] } }
diff --git a/components/sessions/content/content_record_password_state.cc b/components/sessions/content/content_record_password_state.cc index 538450a..c9c9a92d 100644 --- a/components/sessions/content/content_record_password_state.cc +++ b/components/sessions/content/content_record_password_state.cc
@@ -13,30 +13,44 @@ // We stash an enum value in the first character of the string16 that is // associated with this key. const char kPasswordStateKey[] = "sessions_password_state"; -} + +class PasswordStateData : public base::SupportsUserData::Data { + public: + explicit PasswordStateData( + SerializedNavigationEntry::PasswordState password_state) + : password_state_(password_state) {} + ~PasswordStateData() override = default; + + SerializedNavigationEntry::PasswordState password_state() const { + return password_state_; + } + + // base::SupportsUserData::Data: + std::unique_ptr<Data> Clone() override { + return std::make_unique<PasswordStateData>(password_state_); + } + + private: + const SerializedNavigationEntry::PasswordState password_state_; + + DISALLOW_COPY_AND_ASSIGN(PasswordStateData); +}; + +} // namespace SerializedNavigationEntry::PasswordState GetPasswordStateFromNavigation( content::NavigationEntry* entry) { - base::string16 password_state_str; - if (!entry->GetExtraData(kPasswordStateKey, &password_state_str) || - password_state_str.size() != 1) { - return SerializedNavigationEntry::PASSWORD_STATE_UNKNOWN; - } - - SerializedNavigationEntry::PasswordState state = - static_cast<SerializedNavigationEntry::PasswordState>( - password_state_str[0]); - - DCHECK_GE(state, SerializedNavigationEntry::PASSWORD_STATE_UNKNOWN); - DCHECK_LE(state, SerializedNavigationEntry::HAS_PASSWORD_FIELD); - return state; + PasswordStateData* data = + static_cast<PasswordStateData*>(entry->GetUserData(kPasswordStateKey)); + return data ? data->password_state() + : SerializedNavigationEntry::PASSWORD_STATE_UNKNOWN; } void SetPasswordStateInNavigation( SerializedNavigationEntry::PasswordState state, content::NavigationEntry* entry) { - base::string16 password_state_str(1, static_cast<uint16_t>(state)); - entry->SetExtraData(kPasswordStateKey, password_state_str); + entry->SetUserData(kPasswordStateKey, + std::make_unique<PasswordStateData>(state)); } } // namespace sessions
diff --git a/components/sessions/content/content_serialized_navigation_builder_unittest.cc b/components/sessions/content/content_serialized_navigation_builder_unittest.cc index 5fba63f5..363de14 100644 --- a/components/sessions/content/content_serialized_navigation_builder_unittest.cc +++ b/components/sessions/content/content_serialized_navigation_builder_unittest.cc
@@ -26,24 +26,31 @@ const char kExtendedInfoKey2[] = "Key 2"; const char kExtendedInfoValue2[] = "Value 2"; +struct TestData : public base::SupportsUserData::Data { + explicit TestData(const std::string& string) : string(string) {} + ~TestData() override = default; + + std::string string; +}; + class TestExtendedInfoHandler : public ExtendedInfoHandler { public: - explicit TestExtendedInfoHandler(const std::string& key) : key_(key) {} + explicit TestExtendedInfoHandler(const char* key) : key_(key) {} ~TestExtendedInfoHandler() override {} + // ExtendedInfoHandler: std::string GetExtendedInfo(content::NavigationEntry* entry) const override { - base::string16 data; - entry->GetExtraData(key_, &data); - return base::UTF16ToASCII(data); + TestData* test_data = static_cast<TestData*>(entry->GetUserData(key_)); + return test_data ? test_data->string : std::string(); } void RestoreExtendedInfo(const std::string& info, content::NavigationEntry* entry) override { - entry->SetExtraData(key_, base::ASCIIToUTF16(info)); + entry->SetUserData(key_, std::make_unique<TestData>(info)); } private: - std::string key_; + const char* key_; DISALLOW_COPY_AND_ASSIGN(TestExtendedInfoHandler); }; @@ -80,10 +87,10 @@ } void SetExtendedInfoForTest(content::NavigationEntry* entry) { - entry->SetExtraData(kExtendedInfoKey1, - base::ASCIIToUTF16(kExtendedInfoValue1)); - entry->SetExtraData(kExtendedInfoKey2, - base::ASCIIToUTF16(kExtendedInfoValue2)); + entry->SetUserData(kExtendedInfoKey1, + std::make_unique<TestData>(kExtendedInfoValue1)); + entry->SetUserData(kExtendedInfoKey2, + std::make_unique<TestData>(kExtendedInfoValue2)); } } // namespace @@ -220,13 +227,14 @@ EXPECT_EQ(test_data::kVirtualURL, new_navigation_entry->GetRedirectChain()[2]); - base::string16 extra_data; - EXPECT_TRUE( - new_navigation_entry->GetExtraData(kExtendedInfoKey1, &extra_data)); - EXPECT_EQ(kExtendedInfoValue1, base::UTF16ToASCII(extra_data)); - EXPECT_TRUE( - new_navigation_entry->GetExtraData(kExtendedInfoKey2, &extra_data)); - EXPECT_EQ(kExtendedInfoValue2, base::UTF16ToASCII(extra_data)); + TestData* test_data = static_cast<TestData*>( + new_navigation_entry->GetUserData(kExtendedInfoKey1)); + ASSERT_TRUE(test_data); + EXPECT_EQ(kExtendedInfoValue1, test_data->string); + test_data = static_cast<TestData*>( + new_navigation_entry->GetUserData(kExtendedInfoKey2)); + ASSERT_TRUE(test_data); + EXPECT_EQ(kExtendedInfoValue2, test_data->string); } TEST_F(ContentSerializedNavigationBuilderTest, SetPasswordState) {
diff --git a/components/sessions/ios/DEPS b/components/sessions/ios/DEPS index 0fc0ddd..a5618a0 100644 --- a/components/sessions/ios/DEPS +++ b/components/sessions/ios/DEPS
@@ -1,3 +1,4 @@ include_rules = [ + "+ios/web/common", "+ios/web/public", ]
diff --git a/components/sessions/ios/ios_serialized_navigation_driver.cc b/components/sessions/ios/ios_serialized_navigation_driver.cc index 5c53c21a..e9740dcd6 100644 --- a/components/sessions/ios/ios_serialized_navigation_driver.cc +++ b/components/sessions/ios/ios_serialized_navigation_driver.cc
@@ -6,8 +6,8 @@ #include "base/memory/singleton.h" #include "components/sessions/core/serialized_navigation_entry.h" +#include "ios/web/common/referrer_util.h" #include "ios/web/public/referrer.h" -#include "ios/web/public/referrer_util.h" namespace sessions {
diff --git a/components/sync/base/model_type.cc b/components/sync/base/model_type.cc index e5f15af..4ea35bed 100644 --- a/components/sync/base/model_type.cc +++ b/components/sync/base/model_type.cc
@@ -161,14 +161,14 @@ sync_pb::EntitySpecifics::kExperimentsFieldNumber, 19}, }; -static_assert(base::size(kModelTypeInfoMap) == MODEL_TYPE_COUNT, - "kModelTypeInfoMap should have MODEL_TYPE_COUNT elements"); +static_assert(base::size(kModelTypeInfoMap) == ModelType::NUM_ENTRIES, + "kModelTypeInfoMap should have ModelType::NUM_ENTRIES elements"); -static_assert(44 == syncer::MODEL_TYPE_COUNT, +static_assert(44 == syncer::ModelType::NUM_ENTRIES, "When adding a new type, update enum SyncModelTypes in enums.xml " "and suffix SyncModelType in histograms.xml."); -static_assert(44 == syncer::MODEL_TYPE_COUNT, +static_assert(44 == syncer::ModelType::NUM_ENTRIES, "When adding a new type, update kAllocatorDumpNameWhitelist in " "base/trace_event/memory_infra_background_whitelist.cc."); @@ -304,7 +304,7 @@ case DEPRECATED_EXPERIMENTS: specifics->mutable_experiments(); break; - case MODEL_TYPE_COUNT: + case ModelType::NUM_ENTRIES: NOTREACHED() << "No default field value for " << ModelTypeToString(type); break; } @@ -354,7 +354,7 @@ } ModelType GetModelTypeFromSpecifics(const sync_pb::EntitySpecifics& specifics) { - static_assert(44 == MODEL_TYPE_COUNT, + static_assert(44 == ModelType::NUM_ENTRIES, "When adding new protocol types, the following type lookup " "logic must be updated."); if (specifics.has_bookmark()) @@ -457,7 +457,7 @@ } ModelTypeSet EncryptableUserTypes() { - static_assert(44 == MODEL_TYPE_COUNT, + static_assert(44 == ModelType::NUM_ENTRIES, "If adding an unencryptable type, remove from " "encryptable_user_types below."); ModelTypeSet encryptable_user_types = UserTypes(); @@ -502,7 +502,7 @@ // This is used in serialization routines as well as for displaying debug // information. Do not attempt to change these string values unless you know // what you're doing. - if (model_type >= UNSPECIFIED && model_type < MODEL_TYPE_COUNT) + if (model_type >= UNSPECIFIED && model_type < ModelType::NUM_ENTRIES) return kModelTypeInfoMap[model_type].model_type_string; NOTREACHED() << "No known extension for model type."; return "Invalid"; @@ -510,7 +510,7 @@ const char* ModelTypeToHistogramSuffix(ModelType model_type) { DCHECK_GE(model_type, UNSPECIFIED); - DCHECK_LT(model_type, MODEL_TYPE_COUNT); + DCHECK_LT(model_type, ModelType::NUM_ENTRIES); // We use the same string that is used for notification types because they // satisfy all we need (being stable and explanatory). @@ -525,13 +525,13 @@ // changes to this list. int ModelTypeToHistogramInt(ModelType model_type) { DCHECK_GE(model_type, UNSPECIFIED); - DCHECK_LT(model_type, MODEL_TYPE_COUNT); + DCHECK_LT(model_type, ModelType::NUM_ENTRIES); return kModelTypeInfoMap[model_type].model_type_histogram_val; } int ModelTypeToStableIdentifier(ModelType model_type) { DCHECK_GE(model_type, UNSPECIFIED); - DCHECK_LT(model_type, MODEL_TYPE_COUNT); + DCHECK_LT(model_type, ModelType::NUM_ENTRIES); // Make sure the value is stable and positive. return ModelTypeToHistogramInt(model_type) + 1; } @@ -645,7 +645,8 @@ } bool IsRealDataType(ModelType model_type) { - return model_type >= FIRST_REAL_MODEL_TYPE && model_type < MODEL_TYPE_COUNT; + return model_type >= FIRST_REAL_MODEL_TYPE && + model_type < ModelType::NUM_ENTRIES; } bool IsProxyType(ModelType model_type) {
diff --git a/components/sync/base/model_type.h b/components/sync/base/model_type.h index 3253714..3bf14c1 100644 --- a/components/sync/base/model_type.h +++ b/components/sync/base/model_type.h
@@ -156,7 +156,7 @@ DEPRECATED_EXPERIMENTS, LAST_REAL_MODEL_TYPE = DEPRECATED_EXPERIMENTS, - MODEL_TYPE_COUNT, + NUM_ENTRIES, }; using ModelTypeSet = @@ -166,7 +166,7 @@ inline ModelType ModelTypeFromInt(int i) { DCHECK_GE(i, 0); - DCHECK_LT(i, MODEL_TYPE_COUNT); + DCHECK_LT(i, ModelType::NUM_ENTRIES); return static_cast<ModelType>(i); }
diff --git a/components/sync/base/model_type_unittest.cc b/components/sync/base/model_type_unittest.cc index 32acbe1..c318006 100644 --- a/components/sync/base/model_type_unittest.cc +++ b/components/sync/base/model_type_unittest.cc
@@ -18,7 +18,7 @@ class ModelTypeTest : public testing::Test {}; TEST_F(ModelTypeTest, ModelTypeToValue) { - for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { + for (int i = FIRST_REAL_MODEL_TYPE; i < ModelType::NUM_ENTRIES; ++i) { ModelType model_type = ModelTypeFromInt(i); base::ExpectStringValue(ModelTypeToString(model_type), *ModelTypeToValue(model_type)); @@ -42,7 +42,7 @@ TEST_F(ModelTypeTest, IsRealDataType) { EXPECT_FALSE(IsRealDataType(UNSPECIFIED)); - EXPECT_FALSE(IsRealDataType(MODEL_TYPE_COUNT)); + EXPECT_FALSE(IsRealDataType(ModelType::NUM_ENTRIES)); EXPECT_FALSE(IsRealDataType(TOP_LEVEL_FOLDER)); EXPECT_TRUE(IsRealDataType(FIRST_REAL_MODEL_TYPE)); EXPECT_TRUE(IsRealDataType(BOOKMARKS)); @@ -54,7 +54,7 @@ TEST_F(ModelTypeTest, IsProxyType) { EXPECT_FALSE(IsProxyType(BOOKMARKS)); - EXPECT_FALSE(IsProxyType(MODEL_TYPE_COUNT)); + EXPECT_FALSE(IsProxyType(ModelType::NUM_ENTRIES)); EXPECT_TRUE(IsProxyType(PROXY_TABS)); } @@ -83,10 +83,10 @@ << "Expected histogram values to be unique"; // This is not necessary for the mapping to be valid, but most instances of - // UMA_HISTOGRAM that use this mapping specify MODEL_TYPE_COUNT as the + // UMA_HISTOGRAM that use this mapping specify ModelType::NUM_ENTRIES as the // maximum possible value. If you break this assumption, you should update // those histograms. - EXPECT_LT(histogram_value, MODEL_TYPE_COUNT); + EXPECT_LT(histogram_value, ModelType::NUM_ENTRIES); } }
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc index 3d412e5..3d1d6df1 100644 --- a/components/sync/base/sync_prefs.cc +++ b/components/sync/base/sync_prefs.cc
@@ -408,7 +408,7 @@ case SEND_TAB_TO_SELF: case NIGORI: case DEPRECATED_EXPERIMENTS: - case MODEL_TYPE_COUNT: + case ModelType::NUM_ENTRIES: case SESSIONS: break; case BOOKMARKS:
diff --git a/components/sync/driver/async_directory_type_controller.cc b/components/sync/driver/async_directory_type_controller.cc index 8b07886..b9fe01617 100644 --- a/components/sync/driver/async_directory_type_controller.cc +++ b/components/sync/driver/async_directory_type_controller.cc
@@ -214,7 +214,7 @@ // TODO(wychen): enum uma should be strongly typed. crbug.com/661401 UMA_HISTOGRAM_ENUMERATION("Sync.DataTypeStartFailures2", ModelTypeToHistogramInt(type()), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); #define PER_DATA_TYPE_MACRO(type_str) \ UMA_HISTOGRAM_ENUMERATION("Sync." type_str "ConfigureFailure", result, \ MAX_CONFIGURE_RESULT);
diff --git a/components/sync/driver/backend_migrator.cc b/components/sync/driver/backend_migrator.cc index 696eda69..648078e 100644 --- a/components/sync/driver/backend_migrator.cc +++ b/components/sync/driver/backend_migrator.cc
@@ -118,7 +118,7 @@ ModelTypeSet GetUnsyncedDataTypes(UserShare* user_share) { ReadTransaction trans(FROM_HERE, user_share); ModelTypeSet unsynced_data_types; - for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { + for (int i = FIRST_REAL_MODEL_TYPE; i < ModelType::NUM_ENTRIES; ++i) { ModelType type = ModelTypeFromInt(i); sync_pb::DataTypeProgressMarker progress_marker; trans.GetDirectory()->GetDownloadProgress(type, &progress_marker);
diff --git a/components/sync/driver/backend_migrator_unittest.cc b/components/sync/driver/backend_migrator_unittest.cc index 21f059f..53ba320 100644 --- a/components/sync/driver/backend_migrator_unittest.cc +++ b/components/sync/driver/backend_migrator_unittest.cc
@@ -53,7 +53,7 @@ // types as synced. void SetUnsyncedTypes(ModelTypeSet unsynced_types) { WriteTransaction trans(FROM_HERE, test_user_share_.user_share()); - for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { + for (int i = FIRST_REAL_MODEL_TYPE; i < ModelType::NUM_ENTRIES; ++i) { ModelType type = ModelTypeFromInt(i); sync_pb::DataTypeProgressMarker progress_marker; if (!unsynced_types.Has(type)) {
diff --git a/components/sync/driver/data_type_manager_impl.cc b/components/sync/driver/data_type_manager_impl.cc index 9dc92262..7416dee 100644 --- a/components/sync/driver/data_type_manager_impl.cc +++ b/components/sync/driver/data_type_manager_impl.cc
@@ -262,7 +262,7 @@ // TODO(wychen): enum uma should be strongly typed. crbug.com/661401 UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureDataTypes", ModelTypeToHistogramInt(type), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); } }
diff --git a/components/sync/driver/directory_data_type_controller.cc b/components/sync/driver/directory_data_type_controller.cc index 85926dc..ae12bf1 100644 --- a/components/sync/driver/directory_data_type_controller.cc +++ b/components/sync/driver/directory_data_type_controller.cc
@@ -75,8 +75,9 @@ void DirectoryDataTypeController::GetStatusCounters( StatusCountersCallback callback) { - std::vector<int> num_entries_by_type(syncer::MODEL_TYPE_COUNT, 0); - std::vector<int> num_to_delete_entries_by_type(syncer::MODEL_TYPE_COUNT, 0); + std::vector<int> num_entries_by_type(syncer::ModelType::NUM_ENTRIES, 0); + std::vector<int> num_to_delete_entries_by_type(syncer::ModelType::NUM_ENTRIES, + 0); sync_service_->GetUserShare()->directory->CollectMetaHandleCounts( &num_entries_by_type, &num_to_delete_entries_by_type); syncer::StatusCounters counters;
diff --git a/components/sync/driver/frontend_data_type_controller.cc b/components/sync/driver/frontend_data_type_controller.cc index 9d3be020..55a5c9b5 100644 --- a/components/sync/driver/frontend_data_type_controller.cc +++ b/components/sync/driver/frontend_data_type_controller.cc
@@ -238,7 +238,7 @@ // TODO(wychen): enum uma should be strongly typed. crbug.com/661401 UMA_HISTOGRAM_ENUMERATION("Sync.DataTypeStartFailures2", ModelTypeToHistogramInt(type()), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); #define PER_DATA_TYPE_MACRO(type_str) \ UMA_HISTOGRAM_ENUMERATION("Sync." type_str "ConfigureFailure", result, \ MAX_CONFIGURE_RESULT);
diff --git a/components/sync/driver/glue/sync_backend_host_core.cc b/components/sync/driver/glue/sync_backend_host_core.cc index 59942dd..41ede0406 100644 --- a/components/sync/driver/glue/sync_backend_host_core.cc +++ b/components/sync/driver/glue/sync_backend_host_core.cc
@@ -59,13 +59,13 @@ void RecordPerModelTypeInvalidation(int model_type, bool is_grouped) { UMA_HISTOGRAM_ENUMERATION("Sync.InvalidationPerModelType", model_type, - static_cast<int>(syncer::MODEL_TYPE_COUNT)); + static_cast<int>(syncer::ModelType::NUM_ENTRIES)); if (!is_grouped) { // When recording metrics it's important to distinguish between // many/one case, since "many" aka grouped case is only common in // the deprecated implementation. UMA_HISTOGRAM_ENUMERATION("Sync.NonGroupedInvalidation", model_type, - static_cast<int>(syncer::MODEL_TYPE_COUNT)); + static_cast<int>(syncer::ModelType::NUM_ENTRIES)); } } @@ -267,10 +267,10 @@ << last_invalidation->second; redundant_invalidation = true; UMA_HISTOGRAM_ENUMERATION("Sync.RedundantInvalidationPerModelType", type, - static_cast<int>(syncer::MODEL_TYPE_COUNT)); + static_cast<int>(syncer::ModelType::NUM_ENTRIES)); } else { UMA_HISTOGRAM_ENUMERATION("Sync.NonRedundantInvalidationPerModelType", type, - static_cast<int>(syncer::MODEL_TYPE_COUNT)); + static_cast<int>(syncer::ModelType::NUM_ENTRIES)); } return !fcm_invalidation && redundant_invalidation; @@ -299,7 +299,7 @@ if (!is_grouped && !invalidation.is_unknown_version()) { UMA_HISTOGRAM_ENUMERATION("Sync.NonGroupedInvalidationKnownVersion", ModelTypeToHistogramInt(type), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); } std::unique_ptr<InvalidationInterface> inv_adapter( new InvalidationAdapter(invalidation));
diff --git a/components/sync/driver/model_association_manager.cc b/components/sync/driver/model_association_manager.cc index 18b3acb..8249e12 100644 --- a/components/sync/driver/model_association_manager.cc +++ b/components/sync/driver/model_association_manager.cc
@@ -50,7 +50,7 @@ SEND_TAB_TO_SELF, SECURITY_EVENTS}; static_assert(base::size(kStartOrder) == - MODEL_TYPE_COUNT - FIRST_REAL_MODEL_TYPE, + ModelType::NUM_ENTRIES - FIRST_REAL_MODEL_TYPE, "When adding a new type, update kStartOrder."); // The amount of time we wait for association to finish. If some types haven't @@ -449,7 +449,7 @@ // TODO(wychen): enum uma should be strongly typed. crbug.com/661401 UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed", ModelTypeToHistogramInt(dtc->type()), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); StopDatatypeImpl(SyncError(FROM_HERE, SyncError::DATATYPE_ERROR, "Association timed out.", dtc->type()), STOP_SYNC, dtc, base::DoNothing());
diff --git a/components/sync/driver/model_type_controller.cc b/components/sync/driver/model_type_controller.cc index 7398c6ca..4dab5b0 100644 --- a/components/sync/driver/model_type_controller.cc +++ b/components/sync/driver/model_type_controller.cc
@@ -292,7 +292,7 @@ // defines quite a different order from the type() enum. UMA_HISTOGRAM_ENUMERATION("Sync.DataTypeStartFailures2", ModelTypeToHistogramInt(type()), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); } void ModelTypeController::RecordRunFailure() const { @@ -302,7 +302,7 @@ // defines quite a different order from the type() enum. UMA_HISTOGRAM_ENUMERATION("Sync.DataTypeRunFailures2", ModelTypeToHistogramInt(type()), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); } void ModelTypeController::OnDelegateStarted(
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc index 9a4949b..12ec1095 100644 --- a/components/sync/driver/profile_sync_service.cc +++ b/components/sync/driver/profile_sync_service.cc
@@ -1397,7 +1397,7 @@ for (ModelType type : chosen_types) { UMA_HISTOGRAM_ENUMERATION("Sync.CustomSync2", ModelTypeToHistogramInt(type), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); } } }
diff --git a/components/sync/driver/startup_controller.cc b/components/sync/driver/startup_controller.cc index 0b7da17..8f6520543 100644 --- a/components/sync/driver/startup_controller.cc +++ b/components/sync/driver/startup_controller.cc
@@ -166,7 +166,7 @@ // TODO(wychen): enum uma should be strongly typed. crbug.com/661401 UMA_HISTOGRAM_ENUMERATION("Sync.Startup.TypeTriggeringInit", ModelTypeToHistogramInt(type), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); if (!start_up_time_.is_null()) { RecordTimeDeferred(); UMA_HISTOGRAM_ENUMERATION("Sync.Startup.DeferredInitTrigger",
diff --git a/components/sync/driver/test_sync_service.cc b/components/sync/driver/test_sync_service.cc index 05c1dad..44d1357 100644 --- a/components/sync/driver/test_sync_service.cc +++ b/components/sync/driver/test_sync_service.cc
@@ -23,9 +23,9 @@ /*num_server_conflicts=*/7, /*notifications_enabled=*/false, /*num_entries=*/0, /*sync_start_time=*/base::Time::Now(), /*poll_finish_time=*/base::Time::Now(), - /*num_entries_by_type=*/std::vector<int>(MODEL_TYPE_COUNT, 0), + /*num_entries_by_type=*/std::vector<int>(ModelType::NUM_ENTRIES, 0), /*num_to_delete_entries_by_type=*/ - std::vector<int>(MODEL_TYPE_COUNT, 0), + std::vector<int>(ModelType::NUM_ENTRIES, 0), /*get_updates_origin=*/sync_pb::SyncEnums::UNKNOWN_ORIGIN, /*poll_interval=*/base::TimeDelta::FromMinutes(30), /*has_remaining_local_changes=*/false);
diff --git a/components/sync/engine/cycle/sync_cycle_snapshot.cc b/components/sync/engine/cycle/sync_cycle_snapshot.cc index e307e2f..f3a4e73 100644 --- a/components/sync/engine/cycle/sync_cycle_snapshot.cc +++ b/components/sync/engine/cycle/sync_cycle_snapshot.cc
@@ -33,8 +33,8 @@ num_server_conflicts_(0), notifications_enabled_(false), num_entries_(0), - num_entries_by_type_(MODEL_TYPE_COUNT, 0), - num_to_delete_entries_by_type_(MODEL_TYPE_COUNT, 0), + num_entries_by_type_(ModelType::NUM_ENTRIES, 0), + num_to_delete_entries_by_type_(ModelType::NUM_ENTRIES, 0), has_remaining_local_changes_(false), is_initialized_(false) {} @@ -106,7 +106,7 @@ std::unique_ptr<base::DictionaryValue> counter_entries( new base::DictionaryValue()); - for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; i++) { + for (int i = FIRST_REAL_MODEL_TYPE; i < ModelType::NUM_ENTRIES; i++) { std::unique_ptr<base::DictionaryValue> type_entries( new base::DictionaryValue()); type_entries->SetInteger("numEntries", num_entries_by_type_[i]);
diff --git a/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc b/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc index 1fbe7d5..e312ba0 100644 --- a/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc +++ b/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc
@@ -47,14 +47,15 @@ const int kNumEncryptionConflicts = 1054; const int kNumHierarchyConflicts = 1055; const int kNumServerConflicts = 1057; - SyncCycleSnapshot snapshot( - model_neutral, download_progress_markers, kIsSilenced, - kNumEncryptionConflicts, kNumHierarchyConflicts, kNumServerConflicts, - false, 0, base::Time::Now(), base::Time::Now(), - std::vector<int>(MODEL_TYPE_COUNT, 0), - std::vector<int>(MODEL_TYPE_COUNT, 0), sync_pb::SyncEnums::UNKNOWN_ORIGIN, - /*poll_interval=*/base::TimeDelta::FromMinutes(30), - /*has_remaining_local_changes=*/false); + SyncCycleSnapshot snapshot(model_neutral, download_progress_markers, + kIsSilenced, kNumEncryptionConflicts, + kNumHierarchyConflicts, kNumServerConflicts, false, + 0, base::Time::Now(), base::Time::Now(), + std::vector<int>(ModelType::NUM_ENTRIES, 0), + std::vector<int>(ModelType::NUM_ENTRIES, 0), + sync_pb::SyncEnums::UNKNOWN_ORIGIN, + /*poll_interval=*/base::TimeDelta::FromMinutes(30), + /*has_remaining_local_changes=*/false); std::unique_ptr<base::DictionaryValue> value(snapshot.ToValue()); EXPECT_EQ(19u, value->size()); ExpectDictIntegerValue(model_neutral.num_successful_commits, *value,
diff --git a/components/sync/engine/sync_backend_registrar_unittest.cc b/components/sync/engine/sync_backend_registrar_unittest.cc index d5e2621b..d595f87 100644 --- a/components/sync/engine/sync_backend_registrar_unittest.cc +++ b/components/sync/engine/sync_backend_registrar_unittest.cc
@@ -62,7 +62,7 @@ } void ExpectHasProcessorsForTypes(ModelTypeSet types) { - for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { + for (int i = FIRST_REAL_MODEL_TYPE; i < ModelType::NUM_ENTRIES; ++i) { ModelType model_type = ModelTypeFromInt(i); EXPECT_EQ(types.Has(model_type), registrar_->IsTypeActivatedForTest(model_type));
diff --git a/components/sync/engine/sync_status.cc b/components/sync/engine/sync_status.cc index e6b0c08..d1d55e2f 100644 --- a/components/sync/engine/sync_status.cc +++ b/components/sync/engine/sync_status.cc
@@ -27,8 +27,8 @@ crypto_has_pending_keys(false), has_keystore_key(false), passphrase_type(PassphraseType::IMPLICIT_PASSPHRASE), - num_entries_by_type(MODEL_TYPE_COUNT, 0), - num_to_delete_entries_by_type(MODEL_TYPE_COUNT, 0) {} + num_entries_by_type(ModelType::NUM_ENTRIES, 0), + num_to_delete_entries_by_type(ModelType::NUM_ENTRIES, 0) {} SyncStatus::SyncStatus(const SyncStatus& other) = default;
diff --git a/components/sync/engine_impl/cycle/sync_cycle.cc b/components/sync/engine_impl/cycle/sync_cycle.cc index 0fc8384..785d313 100644 --- a/components/sync/engine_impl/cycle/sync_cycle.cc +++ b/components/sync/engine_impl/cycle/sync_cycle.cc
@@ -27,7 +27,7 @@ SyncCycleSnapshot SyncCycle::TakeSnapshotWithOrigin( sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin) const { ProgressMarkerMap download_progress_markers; - for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { + for (int i = FIRST_REAL_MODEL_TYPE; i < ModelType::NUM_ENTRIES; ++i) { ModelType type(ModelTypeFromInt(i)); const UpdateHandler* update_handler = context_->model_type_registry()->GetUpdateHandler(type); @@ -43,8 +43,8 @@ // an issue with USS types. syncable::Directory* dir = context_->directory(); - std::vector<int> num_entries_by_type(MODEL_TYPE_COUNT, 0); - std::vector<int> num_to_delete_entries_by_type(MODEL_TYPE_COUNT, 0); + std::vector<int> num_entries_by_type(ModelType::NUM_ENTRIES, 0); + std::vector<int> num_to_delete_entries_by_type(ModelType::NUM_ENTRIES, 0); dir->CollectMetaHandleCounts(&num_entries_by_type, &num_to_delete_entries_by_type);
diff --git a/components/sync/engine_impl/debug_info_event_listener.h b/components/sync/engine_impl/debug_info_event_listener.h index e9cb21f..391b253 100644 --- a/components/sync/engine_impl/debug_info_event_listener.h +++ b/components/sync/engine_impl/debug_info_event_listener.h
@@ -28,7 +28,7 @@ // In order to track datatype association results, we need at least as many // entries as datatypes. Reserve additional space for other kinds of events that // are likely to happen during first sync or startup. -const unsigned int kMaxEntries = MODEL_TYPE_COUNT + 10; +const unsigned int kMaxEntries = ModelType::NUM_ENTRIES + 10; // Listens to events and records them in a queue. And passes the events to // syncer when requested.
diff --git a/components/sync/engine_impl/js_mutation_event_observer_unittest.cc b/components/sync/engine_impl/js_mutation_event_observer_unittest.cc index 0159fea..49f2424 100644 --- a/components/sync/engine_impl/js_mutation_event_observer_unittest.cc +++ b/components/sync/engine_impl/js_mutation_event_observer_unittest.cc
@@ -46,8 +46,8 @@ // We don't test with passwords as that requires additional setup. // Build a list of example ChangeRecords. - ChangeRecord changes[MODEL_TYPE_COUNT]; - for (int i = AUTOFILL_PROFILE; i < MODEL_TYPE_COUNT; ++i) { + ChangeRecord changes[ModelType::NUM_ENTRIES]; + for (int i = AUTOFILL_PROFILE; i < ModelType::NUM_ENTRIES; ++i) { changes[i].id = i; switch (i % 3) { case 0: @@ -67,13 +67,13 @@ // starting from changes[i]. // Set expectations for each data type. - for (int i = AUTOFILL_PROFILE; i < MODEL_TYPE_COUNT; ++i) { + for (int i = AUTOFILL_PROFILE; i < ModelType::NUM_ENTRIES; ++i) { const std::string& model_type_str = ModelTypeToString(ModelTypeFromInt(i)); base::DictionaryValue expected_details; expected_details.SetString("modelType", model_type_str); expected_details.SetString("writeTransactionId", "0"); auto expected_changes = std::make_unique<base::ListValue>(); - for (int j = i; j < MODEL_TYPE_COUNT; ++j) { + for (int j = i; j < ModelType::NUM_ENTRIES; ++j) { expected_changes->Append(changes[j].ToValue()); } expected_details.Set("changes", std::move(expected_changes)); @@ -83,7 +83,7 @@ } // Fire OnChangesApplied() for each data type. - for (int i = AUTOFILL_PROFILE; i < MODEL_TYPE_COUNT; ++i) { + for (int i = AUTOFILL_PROFILE; i < ModelType::NUM_ENTRIES; ++i) { ChangeRecordList local_changes(std::begin(changes) + i, std::end(changes)); js_mutation_event_observer_.OnChangesApplied( ModelTypeFromInt(i), 0, ImmutableChangeRecordList(&local_changes)); @@ -95,7 +95,7 @@ TEST_F(JsMutationEventObserverTest, OnChangesComplete) { InSequence dummy; - for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { + for (int i = FIRST_REAL_MODEL_TYPE; i < ModelType::NUM_ENTRIES; ++i) { base::DictionaryValue expected_details; expected_details.SetString("modelType", ModelTypeToString(ModelTypeFromInt(i))); @@ -104,7 +104,7 @@ HasDetailsAsDictionary(expected_details))); } - for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { + for (int i = FIRST_REAL_MODEL_TYPE; i < ModelType::NUM_ENTRIES; ++i) { js_mutation_event_observer_.OnChangesComplete(ModelTypeFromInt(i)); } PumpLoop();
diff --git a/components/sync/engine_impl/js_sync_encryption_handler_observer_unittest.cc b/components/sync/engine_impl/js_sync_encryption_handler_observer_unittest.cc index 6fda79b2..e44cf33 100644 --- a/components/sync/engine_impl/js_sync_encryption_handler_observer_unittest.cc +++ b/components/sync/engine_impl/js_sync_encryption_handler_observer_unittest.cc
@@ -113,7 +113,7 @@ auto encrypted_type_values = std::make_unique<base::ListValue>(); ModelTypeSet encrypted_types; - for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { + for (int i = FIRST_REAL_MODEL_TYPE; i < ModelType::NUM_ENTRIES; ++i) { ModelType type = ModelTypeFromInt(i); encrypted_types.Put(type); encrypted_type_values->AppendString(ModelTypeToString(type));
diff --git a/components/sync/engine_impl/js_sync_manager_observer_unittest.cc b/components/sync/engine_impl/js_sync_manager_observer_unittest.cc index 35309f85..fcb7d2d 100644 --- a/components/sync/engine_impl/js_sync_manager_observer_unittest.cc +++ b/components/sync/engine_impl/js_sync_manager_observer_unittest.cc
@@ -61,13 +61,14 @@ } TEST_F(JsSyncManagerObserverTest, OnSyncCycleCompleted) { - SyncCycleSnapshot snapshot( - ModelNeutralState(), ProgressMarkerMap(), false, 5, 2, 7, false, 0, - base::Time::Now(), base::Time::Now(), - std::vector<int>(MODEL_TYPE_COUNT, 0), - std::vector<int>(MODEL_TYPE_COUNT, 0), sync_pb::SyncEnums::UNKNOWN_ORIGIN, - /*poll_interval=*/base::TimeDelta::FromMinutes(30), - /*has_remaining_local_changes=*/false); + SyncCycleSnapshot snapshot(ModelNeutralState(), ProgressMarkerMap(), false, 5, + 2, 7, false, 0, base::Time::Now(), + base::Time::Now(), + std::vector<int>(ModelType::NUM_ENTRIES, 0), + std::vector<int>(ModelType::NUM_ENTRIES, 0), + sync_pb::SyncEnums::UNKNOWN_ORIGIN, + /*poll_interval=*/base::TimeDelta::FromMinutes(30), + /*has_remaining_local_changes=*/false); base::DictionaryValue expected_details; expected_details.Set("snapshot", snapshot.ToValue());
diff --git a/components/sync/engine_impl/model_type_registry.cc b/components/sync/engine_impl/model_type_registry.cc index 0420cb5..ee4b09c 100644 --- a/components/sync/engine_impl/model_type_registry.cc +++ b/components/sync/engine_impl/model_type_registry.cc
@@ -136,7 +136,7 @@ // TODO(wychen): enum uma should be strongly typed. crbug.com/661401 UMA_HISTOGRAM_ENUMERATION("Sync.USSMigrationSuccess", ModelTypeToHistogramInt(type), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); // If we succesfully migrated, purge the directory of data for the type. // Purging removes the directory's local copy of the data only. directory()->PurgeEntriesWithTypeIn(ModelTypeSet(type), ModelTypeSet(), @@ -145,7 +145,7 @@ // TODO(wychen): enum uma should be strongly typed. crbug.com/661401 UMA_HISTOGRAM_ENUMERATION("Sync.USSMigrationFailure", ModelTypeToHistogramInt(type), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); } // Note that a partial failure may still contribute to the counts histogram.
diff --git a/components/sync/engine_impl/sync_manager_impl.cc b/components/sync/engine_impl/sync_manager_impl.cc index 4473f84..093e6ae 100644 --- a/components/sync/engine_impl/sync_manager_impl.cc +++ b/components/sync/engine_impl/sync_manager_impl.cc
@@ -148,7 +148,7 @@ observing_network_connectivity_changes_(false), weak_ptr_factory_(this) { // Pre-fill |notification_info_map_|. - for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { + for (int i = FIRST_REAL_MODEL_TYPE; i < ModelType::NUM_ENTRIES; ++i) { notification_info_map_.insert( std::make_pair(ModelTypeFromInt(i), NotificationInfo())); } @@ -783,7 +783,7 @@ LOG_IF(WARNING, !change_records_.empty()) << "CALCULATE_CHANGES called with unapplied old changes."; - ChangeReorderBuffer change_buffers[MODEL_TYPE_COUNT]; + ChangeReorderBuffer change_buffers[ModelType::NUM_ENTRIES]; Cryptographer* crypto = directory()->GetCryptographer(trans); const syncable::ImmutableEntryKernelMutationMap& mutations = @@ -812,7 +812,7 @@ } ReadTransaction read_trans(GetUserShare(), trans); - for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { + for (int i = FIRST_REAL_MODEL_TYPE; i < ModelType::NUM_ENTRIES; ++i) { if (!change_buffers[i].IsEmpty()) { if (change_buffers[i].GetAllChangesInTreeOrder(&read_trans, &(change_records_[i]))) {
diff --git a/components/sync/engine_impl/syncer_proto_util.cc b/components/sync/engine_impl/syncer_proto_util.cc index db55ed5..2902f7e5 100644 --- a/components/sync/engine_impl/syncer_proto_util.cc +++ b/components/sync/engine_impl/syncer_proto_util.cc
@@ -368,7 +368,7 @@ "Sync.PostedDataTypeGetUpdatesRequest", ModelTypeToHistogramInt(GetModelTypeFromSpecificsFieldNumber( progress_marker.data_type_id())), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); } }
diff --git a/components/sync/model/data_type_error_handler_impl.cc b/components/sync/model/data_type_error_handler_impl.cc index af4b3b68..b05e98f 100644 --- a/components/sync/model/data_type_error_handler_impl.cc +++ b/components/sync/model/data_type_error_handler_impl.cc
@@ -25,7 +25,7 @@ // TODO(wychen): enum uma should be strongly typed. crbug.com/661401 UMA_HISTOGRAM_ENUMERATION("Sync.DataTypeRunFailures2", ModelTypeToHistogramInt(error.model_type()), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); ui_thread_->PostTask(error.location(), base::BindOnce(sync_callback_, error)); }
diff --git a/components/sync/model_impl/blocking_model_type_store_impl.cc b/components/sync/model_impl/blocking_model_type_store_impl.cc index c95024cc..5bc511c8 100644 --- a/components/sync/model_impl/blocking_model_type_store_impl.cc +++ b/components/sync/model_impl/blocking_model_type_store_impl.cc
@@ -242,7 +242,7 @@ DCHECK_EQ(write_batch_impl->GetModelType(), type_); UMA_HISTOGRAM_ENUMERATION("Sync.ModelTypeStoreCommitCount", ModelTypeToHistogramInt(type_), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); return backend_->WriteModifications( LevelDbWriteBatch::ToLevelDbWriteBatch(std::move(write_batch_impl))); }
diff --git a/components/sync/model_impl/client_tag_based_model_type_processor.cc b/components/sync/model_impl/client_tag_based_model_type_processor.cc index 649b67d..f7940d9 100644 --- a/components/sync/model_impl/client_tag_based_model_type_processor.cc +++ b/components/sync/model_impl/client_tag_based_model_type_processor.cc
@@ -398,7 +398,7 @@ // Ignore changes that don't actually change anything. UMA_HISTOGRAM_ENUMERATION("Sync.ModelTypeRedundantPut", ModelTypeToHistogramInt(type_), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); return; } @@ -1137,7 +1137,7 @@ storage_keys_to_untrack.push_back(storage_key); UMA_HISTOGRAM_ENUMERATION("Sync.ModelTypeOrphanMetadata", ModelTypeToHistogramInt(type_), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); } if (storage_keys_to_untrack.empty()) {
diff --git a/components/sync/protocol/proto_value_conversions_unittest.cc b/components/sync/protocol/proto_value_conversions_unittest.cc index ea2176fd..d53a888f 100644 --- a/components/sync/protocol/proto_value_conversions_unittest.cc +++ b/components/sync/protocol/proto_value_conversions_unittest.cc
@@ -60,7 +60,7 @@ DEFINE_SPECIFICS_TO_VALUE_TEST(encrypted) -static_assert(44 == syncer::MODEL_TYPE_COUNT, +static_assert(44 == syncer::ModelType::NUM_ENTRIES, "When adding a new field, add a DEFINE_SPECIFICS_TO_VALUE_TEST " "for your field below, and optionally a test for the specific " "conversions.");
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h index 56c45ce9..7469b54 100644 --- a/components/sync/protocol/proto_visitors.h +++ b/components/sync/protocol/proto_visitors.h
@@ -367,7 +367,7 @@ } VISIT_PROTO_FIELDS(const sync_pb::EntitySpecifics& proto) { - static_assert(44 == MODEL_TYPE_COUNT, + static_assert(44 == ModelType::NUM_ENTRIES, "When adding a new protocol type, you will likely need to add " "it here as well."); VISIT(encrypted);
diff --git a/components/sync/syncable/directory.cc b/components/sync/syncable/directory.cc index 1c477bc..8bd6110 100644 --- a/components/sync/syncable/directory.cc +++ b/components/sync/syncable/directory.cc
@@ -828,7 +828,7 @@ base::StringPrintf("sync/0x%" PRIXPTR, reinterpret_cast<uintptr_t>(this)); size_t kernel_memory_usage; - size_t model_type_entry_count[MODEL_TYPE_COUNT] = {0}; + size_t model_type_entry_count[ModelType::NUM_ENTRIES] = {0}; { using base::trace_event::EstimateMemoryUsage; @@ -860,7 +860,7 @@ } // Similar to UploadModelTypeEntryCount() - for (size_t i = FIRST_REAL_MODEL_TYPE; i != MODEL_TYPE_COUNT; ++i) { + for (size_t i = FIRST_REAL_MODEL_TYPE; i != ModelType::NUM_ENTRIES; ++i) { ModelType model_type = static_cast<ModelType>(i); std::string notification_type; if (RealModelTypeToNotificationType(model_type, ¬ification_type)) { @@ -1114,7 +1114,7 @@ std::vector<int64_t>* result) { result->clear(); ScopedKernelLock lock(this); - for (int i = UNSPECIFIED; i < MODEL_TYPE_COUNT; ++i) { + for (int i = UNSPECIFIED; i < ModelType::NUM_ENTRIES; ++i) { const ModelType type = ModelTypeFromInt(i); if (server_types.Has(type)) { std::copy(kernel_->unapplied_update_metahandles[type].begin(),
diff --git a/components/sync/syncable/directory.h b/components/sync/syncable/directory.h index fb340d4..26b70b61 100644 --- a/components/sync/syncable/directory.h +++ b/components/sync/syncable/directory.h
@@ -99,14 +99,14 @@ size_t EstimateMemoryUsage() const; // Last sync timestamp fetched from the server. - sync_pb::DataTypeProgressMarker download_progress[MODEL_TYPE_COUNT]; + sync_pb::DataTypeProgressMarker download_progress[ModelType::NUM_ENTRIES]; // Sync-side transaction version per data type. Monotonically incremented // when updating native model. A copy is also saved in native model. // Later out-of-sync models can be detected and fixed by comparing // transaction versions of sync model and native model. // TODO(hatiaol): implement detection and fixing of out-of-sync models. // Bug 154858. - int64_t transaction_version[MODEL_TYPE_COUNT]; + int64_t transaction_version[ModelType::NUM_ENTRIES]; // The store birthday we were given by the server. Contents are opaque to // the client. std::string store_birthday; @@ -115,7 +115,7 @@ // ChipBag defined in sync.proto. It can contains null characters. std::string bag_of_chips; // The per-datatype context. - sync_pb::DataTypeContext datatype_context[MODEL_TYPE_COUNT]; + sync_pb::DataTypeContext datatype_context[ModelType::NUM_ENTRIES]; }; // What the Directory needs on initialization to create itself and its Kernel. @@ -197,7 +197,7 @@ // 3 in-memory indices on bits used extremely frequently by the syncer. // |unapplied_update_metahandles| is keyed by the server model type. - MetahandleSet unapplied_update_metahandles[MODEL_TYPE_COUNT]; + MetahandleSet unapplied_update_metahandles[ModelType::NUM_ENTRIES]; MetahandleSet unsynced_metahandles; // Contains metahandles that are most likely dirty (though not // necessarily). Dirtyness is confirmed in TakeSnapshotForSaveChanges().
diff --git a/components/sync/syncable/nigori_util.cc b/components/sync/syncable/nigori_util.cc index c4c62ce..215c635 100644 --- a/components/sync/syncable/nigori_util.cc +++ b/components/sync/syncable/nigori_util.cc
@@ -214,7 +214,7 @@ << " already match, dropping change."; UMA_HISTOGRAM_ENUMERATION("Sync.ModelTypeRedundantPut", ModelTypeToHistogramInt(type), - static_cast<int>(MODEL_TYPE_COUNT)); + static_cast<int>(ModelType::NUM_ENTRIES)); return true; } @@ -250,7 +250,7 @@ bool encrypt_everything, sync_pb::NigoriSpecifics* nigori) { nigori->set_encrypt_everything(encrypt_everything); - static_assert(44 == MODEL_TYPE_COUNT, + static_assert(44 == ModelType::NUM_ENTRIES, "If adding an encryptable type, update handling below."); nigori->set_encrypt_bookmarks(encrypted_types.Has(BOOKMARKS)); nigori->set_encrypt_preferences(encrypted_types.Has(PREFERENCES)); @@ -287,7 +287,7 @@ return ModelTypeSet::All(); ModelTypeSet encrypted_types; - static_assert(44 == MODEL_TYPE_COUNT, + static_assert(44 == ModelType::NUM_ENTRIES, "If adding an encryptable type, update handling below."); if (nigori.encrypt_bookmarks()) encrypted_types.Put(BOOKMARKS);
diff --git a/components/sync/syncable/parent_child_index.cc b/components/sync/syncable/parent_child_index.cc index c3701af..96735b4 100644 --- a/components/sync/syncable/parent_child_index.cc +++ b/components/sync/syncable/parent_child_index.cc
@@ -41,8 +41,8 @@ ParentChildIndex::ParentChildIndex() { // Pre-allocate these two vectors to the number of model types. - model_type_root_ids_.resize(MODEL_TYPE_COUNT); - type_root_child_sets_.resize(MODEL_TYPE_COUNT); + model_type_root_ids_.resize(ModelType::NUM_ENTRIES); + type_root_child_sets_.resize(ModelType::NUM_ENTRIES); } ParentChildIndex::~ParentChildIndex() {}
diff --git a/components/sync_bookmarks/bookmark_model_associator.cc b/components/sync_bookmarks/bookmark_model_associator.cc index 958a6ffa6..8c09407 100644 --- a/components/sync_bookmarks/bookmark_model_associator.cc +++ b/components/sync_bookmarks/bookmark_model_associator.cc
@@ -966,9 +966,10 @@ context->set_native_model_sync_state(IN_SYNC); } else { // TODO(wychen): enum uma should be strongly typed. crbug.com/661401 - UMA_HISTOGRAM_ENUMERATION("Sync.LocalModelOutOfSync", - ModelTypeToHistogramInt(syncer::BOOKMARKS), - static_cast<int>(syncer::MODEL_TYPE_COUNT)); + UMA_HISTOGRAM_ENUMERATION( + "Sync.LocalModelOutOfSync", + ModelTypeToHistogramInt(syncer::BOOKMARKS), + static_cast<int>(syncer::ModelType::NUM_ENTRIES)); // Clear version on bookmark model so that we only report error once. bookmark_model_->SetNodeSyncTransactionVersion(
diff --git a/components/test/data/update_client/updatecheck_reply_1.xml b/components/test/data/update_client/updatecheck_reply_1.xml deleted file mode 100644 index b6ff48f..0000000 --- a/components/test/data/update_client/updatecheck_reply_1.xml +++ /dev/null
@@ -1,18 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<response protocol='3.1'> - <app appid='jebgalgnebhfojomionfpkfelancnnkf'> - <updatecheck status='ok'> - <urls> - <url codebase='http://localhost/download/'/> - </urls> - <manifest version='1.0' prodversionmin='11.0.1.0'> - <packages> - <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/> - </packages> - </manifest> - <actions> - <action run='this'/> - </actions> - </updatecheck> - </app> -</response>
diff --git a/components/test/data/update_client/updatecheck_reply_4.xml b/components/test/data/update_client/updatecheck_reply_4.xml deleted file mode 100644 index c2d44625..0000000 --- a/components/test/data/update_client/updatecheck_reply_4.xml +++ /dev/null
@@ -1,16 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<response protocol='3.1'> - <daystart elapsed_days='3383' /> - <app appid='jebgalgnebhfojomionfpkfelancnnkf'> - <updatecheck status='ok'> - <urls> - <url codebase='http://localhost/download/'/> - </urls> - <manifest version='1.0' prodversionmin='11.0.1.0'> - <packages> - <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/> - </packages> - </manifest> - </updatecheck> - </app> -</response>
diff --git a/components/test/data/update_client/updatecheck_reply_noupdate.xml b/components/test/data/update_client/updatecheck_reply_noupdate.xml deleted file mode 100644 index 1e18fa1..0000000 --- a/components/test/data/update_client/updatecheck_reply_noupdate.xml +++ /dev/null
@@ -1,10 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<response protocol='3.1'> - <app appid='jebgalgnebhfojomionfpkfelancnnkf'> - <updatecheck status='noupdate'> - <actions> - <action run='this'/> - </actions> - </updatecheck> - </app> -</response>
diff --git a/components/test/data/update_client/updatecheck_reply_parse_error.xml b/components/test/data/update_client/updatecheck_reply_parse_error.xml deleted file mode 100644 index 43efe93..0000000 --- a/components/test/data/update_client/updatecheck_reply_parse_error.xml +++ /dev/null
@@ -1,4 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<response protocol='3.0'> - <app appid='jebgalgnebhfojomionfpkfelancnnkf'></app> -</response>
diff --git a/components/test/data/update_client/updatecheck_reply_unknownapp.xml b/components/test/data/update_client/updatecheck_reply_unknownapp.xml deleted file mode 100644 index f708ec4..0000000 --- a/components/test/data/update_client/updatecheck_reply_unknownapp.xml +++ /dev/null
@@ -1,4 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<response protocol='3.1'> - <app appid='jebgalgnebhfojomionfpkfelancnnkf' status="error-unknownApplication"/> -</response>
diff --git a/components/update_client/BUILD.gn b/components/update_client/BUILD.gn index 06cb620..4a99ebf5 100644 --- a/components/update_client/BUILD.gn +++ b/components/update_client/BUILD.gn
@@ -67,14 +67,10 @@ "protocol_parser.h", "protocol_parser_json.cc", "protocol_parser_json.h", - "protocol_parser_xml.cc", - "protocol_parser_xml.h", "protocol_serializer.cc", "protocol_serializer.h", "protocol_serializer_json.cc", "protocol_serializer_json.h", - "protocol_serializer_xml.cc", - "protocol_serializer_xml.h", "request_sender.cc", "request_sender.h", "task.h", @@ -123,7 +119,6 @@ "//components/version_info:version_info", "//courgette:courgette_lib", "//crypto", - "//third_party/libxml", "//url", ] @@ -179,15 +174,10 @@ "//components/test/data/update_client/jebgalgnebhfojomionfpkfelancnnkf.crx", "//components/test/data/update_client/runaction_test_win.crx3", "//components/test/data/update_client/updatecheck_reply_1.json", - "//components/test/data/update_client/updatecheck_reply_1.xml", "//components/test/data/update_client/updatecheck_reply_4.json", - "//components/test/data/update_client/updatecheck_reply_4.xml", "//components/test/data/update_client/updatecheck_reply_noupdate.json", - "//components/test/data/update_client/updatecheck_reply_noupdate.xml", "//components/test/data/update_client/updatecheck_reply_parse_error.json", - "//components/test/data/update_client/updatecheck_reply_parse_error.xml", "//components/test/data/update_client/updatecheck_reply_unknownapp.json", - "//components/test/data/update_client/updatecheck_reply_unknownapp.xml", ] outputs = [ "{{bundle_resources_dir}}/" + @@ -204,10 +194,8 @@ "persisted_data_unittest.cc", "ping_manager_unittest.cc", "protocol_parser_json_unittest.cc", - "protocol_parser_xml_unittest.cc", "protocol_serializer_json_unittest.cc", "protocol_serializer_unittest.cc", - "protocol_serializer_xml_unittest.cc", "request_sender_unittest.cc", "update_checker_unittest.cc", "update_client_unittest.cc", @@ -240,7 +228,6 @@ "//services/service_manager/public/cpp/test:test_support", "//testing/gmock", "//testing/gtest", - "//third_party/libxml", "//third_party/re2", ] }
diff --git a/components/update_client/DEPS b/components/update_client/DEPS index 0ac27fd..0a397d6 100644 --- a/components/update_client/DEPS +++ b/components/update_client/DEPS
@@ -8,10 +8,8 @@ "+components/version_info", "+courgette", "+crypto", - "+libxml", "+mojo", "+services/service_manager/public", - "+third_party/libxml", "+third_party/re2", "+third_party/zlib", ]
diff --git a/components/update_client/ping_manager_unittest.cc b/components/update_client/ping_manager_unittest.cc index b48a905e..60d078c 100644 --- a/components/update_client/ping_manager_unittest.cc +++ b/components/update_client/ping_manager_unittest.cc
@@ -54,8 +54,6 @@ scoped_refptr<TestConfigurator> config_; scoped_refptr<PingManager> ping_manager_; - bool use_JSON_ = false; - int error_ = -1; std::string response_; @@ -71,8 +69,6 @@ } void PingManagerTest::SetUp() { - use_JSON_ = GetParam(); - config_->SetUseJSON(use_JSON_); ping_manager_ = base::MakeRefCounted<PingManager>(config_); } @@ -138,7 +134,6 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(msg); ASSERT_TRUE(root); const auto* request = root->FindKey("request"); @@ -174,25 +169,6 @@ EXPECT_EQ(3, event.FindKey("eventtype")->GetInt()); EXPECT_EQ("2.0", event.FindKey("nextversion")->GetString()); EXPECT_EQ("1.0", event.FindKey("previousversion")->GetString()); - } else { - constexpr char regex[] = - R"(<\?xml version="1\.0" encoding="UTF-8"\?>)" - R"(<request protocol="3\.1" )" - R"(dedup="cr" acceptformat="crx2,crx3" extra="foo" )" - R"(sessionid="{[-\w]{36}}" requestid="{[-\w]{36}}" )" - R"(updater="fake_prodid" updaterversion="30\.0" prodversion="30\.0" )" - R"(lang="fake_lang" os="\w+" arch="\w+" nacl_arch="[-\w]+" )" - R"((wow64="1" )?)" - R"(updaterchannel="fake_channel_string" )" - R"(prodchannel="fake_channel_string">)" - R"(<hw physmemory="[0-9]+"/>)" - R"(<os platform="Fake Operating System" arch="[,-.\w]+" )" - R"(version="[-.\w]+"( sp="[\s\w]+")?/>)" - R"(<app appid="abc" version="1\.0">)" - R"(<event eventresult="1" eventtype="3" )" - R"(nextversion="2\.0" previousversion="1\.0"/></app></request>)"; - EXPECT_TRUE(RE2::FullMatch(msg, regex)) << msg; - } // Check the ping request does not carry the specific extra request headers. const auto headers = std::get<1>(interceptor->GetRequests()[0]); @@ -219,7 +195,6 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(msg); ASSERT_TRUE(root); const auto* request = root->FindKey("request"); @@ -231,13 +206,6 @@ EXPECT_EQ(3, event.FindKey("eventtype")->GetInt()); EXPECT_EQ("2.0", event.FindKey("nextversion")->GetString()); EXPECT_EQ("1.0", event.FindKey("previousversion")->GetString()); - } else { - constexpr char regex[] = - R"(<app appid="abc" version="1\.0">)" - R"(<event eventresult="0" eventtype="3" )" - R"(nextversion="2\.0" previousversion="1\.0"/></app>)"; - EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; - } interceptor->Reset(); } @@ -267,7 +235,6 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(msg); ASSERT_TRUE(root); const auto* request = root->FindKey("request"); @@ -288,16 +255,6 @@ EXPECT_EQ(-1, event.FindKey("extracode1")->GetInt()); EXPECT_EQ("next fp", event.FindKey("nextfp")->GetString()); EXPECT_EQ("prev fp", event.FindKey("previousfp")->GetString()); - } else { - constexpr char regex[] = - R"(<app appid="abc" version="1\.0">)" - R"(<event differrorcat="4" differrorcode="20" )" - R"(diffextracode1="-10" diffresult="0" errorcat="1" errorcode="2" )" - R"(eventresult="0" eventtype="3" extracode1="-1" nextfp="next fp" )" - R"(nextversion="2\.0" previousfp="prev fp" previousversion="1\.0"/>)" - R"(</app>)"; - EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; - } interceptor->Reset(); } @@ -318,7 +275,6 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(msg); ASSERT_TRUE(root); const auto* request = root->FindKey("request"); @@ -329,13 +285,6 @@ EXPECT_EQ(0, event.FindKey("eventresult")->GetInt()); EXPECT_EQ(3, event.FindKey("eventtype")->GetInt()); EXPECT_EQ("1.0", event.FindKey("previousversion")->GetString()); - } else { - constexpr char regex[] = - R"(<app appid="abc" version="1\.0">)" - R"(<event eventresult="0" eventtype="3" previousversion="1\.0"/>)" - R"(</app>)"; - EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; - } interceptor->Reset(); } @@ -353,7 +302,6 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(msg); ASSERT_TRUE(root); const auto* request = root->FindKey("request"); @@ -365,13 +313,6 @@ EXPECT_EQ(4, event.FindKey("eventtype")->GetInt()); EXPECT_EQ("1.2.3.4", event.FindKey("previousversion")->GetString()); EXPECT_EQ("0", event.FindKey("nextversion")->GetString()); - } else { - constexpr char regex[] = - R"(<app appid="abc" version="1\.2\.3\.4">)" - R"(<event eventresult="1" eventtype="4" )" - R"(nextversion="0" previousversion="1\.2\.3\.4"/></app>)"; - EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; - } interceptor->Reset(); } @@ -418,7 +359,6 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(msg); ASSERT_TRUE(root); const auto* request = root->FindKey("request"); @@ -471,27 +411,6 @@ EXPECT_EQ(9007199254740991, event.FindKey("total")->GetDouble()); EXPECT_EQ("http://host3/path3", event.FindKey("url")->GetString()); } - } else { - constexpr char regex[] = - R"(<app appid="abc" version="1\.0">)" - R"(<event eventresult="1" eventtype="3" )" - R"(nextversion="2\.0" previousversion="1\.0"/>)" - R"(<event download_time_ms="987" )" - R"(downloaded="123" downloader="direct" )" - R"(errorcode="-1" eventresult="0" eventtype="14" )" - R"(nextversion="2\.0" previousversion="1\.0" total="456" )" - R"(url="http://host1/path1"/>)" - R"(<event download_time_ms="9870" downloaded="1230" )" - R"(downloader="bits" )" - R"(eventresult="1" eventtype="14" nextversion="2\.0" )" - R"(previousversion="1\.0" total="4560" url="http://host2/path2"/>)" - R"(<event download_time_ms="9007199254740990" )" - R"(downloaded="9007199254740992" downloader="bits" )" - R"(eventresult="1" eventtype="14" nextversion="2.0" )" - R"(previousversion="1.0" total="9007199254740991" )" - R"(url="http://host3/path3"/></app>)"; - EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; - } interceptor->Reset(); } }
diff --git a/components/update_client/protocol_handler.cc b/components/update_client/protocol_handler.cc index a6b4999..aa547b4 100644 --- a/components/update_client/protocol_handler.cc +++ b/components/update_client/protocol_handler.cc
@@ -4,22 +4,10 @@ #include "components/update_client/protocol_handler.h" #include "components/update_client/protocol_parser_json.h" -#include "components/update_client/protocol_parser_xml.h" #include "components/update_client/protocol_serializer_json.h" -#include "components/update_client/protocol_serializer_xml.h" namespace update_client { -std::unique_ptr<ProtocolParser> ProtocolHandlerFactoryXml::CreateParser() - const { - return std::make_unique<ProtocolParserXml>(); -} - -std::unique_ptr<ProtocolSerializer> -ProtocolHandlerFactoryXml::CreateSerializer() const { - return std::make_unique<ProtocolSerializerXml>(); -} - std::unique_ptr<ProtocolParser> ProtocolHandlerFactoryJSON::CreateParser() const { return std::make_unique<ProtocolParserJSON>();
diff --git a/components/update_client/protocol_handler.h b/components/update_client/protocol_handler.h index cb8e97e..57c8cfd 100644 --- a/components/update_client/protocol_handler.h +++ b/components/update_client/protocol_handler.h
@@ -27,13 +27,6 @@ DISALLOW_COPY_AND_ASSIGN(ProtocolHandlerFactory); }; -class ProtocolHandlerFactoryXml final : public ProtocolHandlerFactory { - public: - // Overrides for ProtocolHandlerFactory. - std::unique_ptr<ProtocolParser> CreateParser() const override; - std::unique_ptr<ProtocolSerializer> CreateSerializer() const override; -}; - class ProtocolHandlerFactoryJSON final : public ProtocolHandlerFactory { public: // Overrides for ProtocolHandlerFactory.
diff --git a/components/update_client/protocol_parser.cc b/components/update_client/protocol_parser.cc index cea8744..7f280c56 100644 --- a/components/update_client/protocol_parser.cc +++ b/components/update_client/protocol_parser.cc
@@ -4,7 +4,6 @@ #include "components/update_client/protocol_parser.h" #include "base/strings/stringprintf.h" -#include "components/update_client/protocol_parser_xml.h" namespace update_client { @@ -53,8 +52,4 @@ return DoParse(response, &results_); } -std::unique_ptr<ProtocolParser> ProtocolParser::Create() { - return std::make_unique<ProtocolParserXml>(); -} - } // namespace update_client
diff --git a/components/update_client/protocol_parser_xml.cc b/components/update_client/protocol_parser_xml.cc deleted file mode 100644 index ace73c1b..0000000 --- a/components/update_client/protocol_parser_xml.cc +++ /dev/null
@@ -1,422 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/update_client/protocol_parser_xml.h" - -#include <stddef.h> - -#include <algorithm> -#include <cstdint> -#include <memory> -#include <vector> - -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/version.h" -#include "components/update_client/protocol_definition.h" -#include "libxml/tree.h" -#include "third_party/libxml/chromium/libxml_utils.h" - -namespace update_client { - -// Checks whether a given node's name matches |expected_name|. -static bool TagNameEquals(const xmlNode* node, const char* expected_name) { - return 0 == strcmp(expected_name, reinterpret_cast<const char*>(node->name)); -} - -// Returns child nodes of |root| with name |name|. -static std::vector<xmlNode*> GetChildren(xmlNode* root, const char* name) { - std::vector<xmlNode*> result; - for (xmlNode* child = root->children; child != nullptr; child = child->next) { - if (!TagNameEquals(child, name)) { - continue; - } - result.push_back(child); - } - return result; -} - -// Returns the value of a named attribute, or the empty string. -static std::string GetAttribute(xmlNode* node, const char* attribute_name) { - const xmlChar* name = reinterpret_cast<const xmlChar*>(attribute_name); - for (xmlAttr* attr = node->properties; attr != nullptr; attr = attr->next) { - if (!xmlStrcmp(attr->name, name) && attr->children && - attr->children->content) { - return std::string( - reinterpret_cast<const char*>(attr->children->content)); - } - } - return std::string(); -} - -// Returns the value of a named attribute, or nullptr . -static std::unique_ptr<std::string> GetAttributePtr( - xmlNode* node, - const char* attribute_name) { - const xmlChar* name = reinterpret_cast<const xmlChar*>(attribute_name); - for (xmlAttr* attr = node->properties; attr != nullptr; attr = attr->next) { - if (!xmlStrcmp(attr->name, name) && attr->children && - attr->children->content) { - return std::make_unique<std::string>( - reinterpret_cast<const char*>(attr->children->content)); - } - } - return nullptr; -} - -// This is used for the xml parser to report errors. This assumes the context -// is a pointer to a std::string where the error message should be appended. -static void XmlErrorFunc(void* context, const char* message, ...) { - va_list args; - va_start(args, message); - std::string* error = static_cast<std::string*>(context); - base::StringAppendV(error, message, args); - va_end(args); -} - -// Utility class for cleaning up the xml document when leaving a scope. -class ScopedXmlDocument { - public: - explicit ScopedXmlDocument(xmlDocPtr document) : document_(document) {} - ~ScopedXmlDocument() { - if (document_) - xmlFreeDoc(document_); - } - - xmlDocPtr get() { return document_; } - - private: - xmlDocPtr document_; -}; - -// Parses the <package> tag. -bool ParsePackageTag(xmlNode* package, - ProtocolParser::Result* result, - std::string* error) { - ProtocolParser::Result::Manifest::Package p; - p.name = GetAttribute(package, "name"); - if (p.name.empty()) { - *error = "Missing name for package."; - return false; - } - - p.namediff = GetAttribute(package, "namediff"); - - // package_fingerprint is optional. It identifies the package, preferably - // with a modified sha256 hash of the package in hex format. - p.fingerprint = GetAttribute(package, "fp"); - - p.hash_sha256 = GetAttribute(package, "hash_sha256"); - int64_t size = 0; - if (base::StringToInt64(GetAttribute(package, "size"), &size) && size >= 0) { - p.size = size; - } - - p.hashdiff_sha256 = GetAttribute(package, "hashdiff_sha256"); - int64_t sizediff = 0; - if (base::StringToInt64(GetAttribute(package, "sizediff"), &sizediff) && - sizediff >= 0) { - p.sizediff = sizediff; - } - - result->manifest.packages.push_back(p); - - return true; -} - -// Parses the <manifest> tag. -bool ParseManifestTag(xmlNode* manifest, - ProtocolParser::Result* result, - std::string* error) { - // Get the version. - result->manifest.version = GetAttribute(manifest, "version"); - if (result->manifest.version.empty()) { - *error = "Missing version for manifest."; - return false; - } - base::Version version(result->manifest.version); - if (!version.IsValid()) { - *error = "Invalid version: '"; - *error += result->manifest.version; - *error += "'."; - return false; - } - - // Get the minimum browser version (not required). - result->manifest.browser_min_version = - GetAttribute(manifest, "prodversionmin"); - if (result->manifest.browser_min_version.length()) { - base::Version browser_min_version(result->manifest.browser_min_version); - if (!browser_min_version.IsValid()) { - *error = "Invalid prodversionmin: '"; - *error += result->manifest.browser_min_version; - *error += "'."; - return false; - } - } - - // Get the <packages> node. - std::vector<xmlNode*> packages = GetChildren(manifest, "packages"); - if (packages.empty()) { - *error = "Missing packages tag on manifest."; - return false; - } - - // Parse each of the <package> tags. - std::vector<xmlNode*> package = GetChildren(packages[0], "package"); - for (size_t i = 0; i != package.size(); ++i) { - if (!ParsePackageTag(package[i], result, error)) - return false; - } - - return true; -} - -// Parses the <urls> tag and its children in the <updatecheck>. -bool ParseUrlsTag(xmlNode* urls, - ProtocolParser::Result* result, - std::string* error) { - // Get the url nodes. - std::vector<xmlNode*> url = GetChildren(urls, "url"); - if (url.empty()) { - *error = "Missing url tags on urls."; - return false; - } - - // Get the list of urls for full and diff updates. - for (size_t i = 0; i != url.size(); ++i) { - const GURL crx_url(GetAttribute(url[i], "codebase")); - if (crx_url.is_valid()) - result->crx_urls.push_back(crx_url); - const GURL crx_diffurl(GetAttribute(url[i], "codebasediff")); - if (crx_diffurl.is_valid()) - result->crx_diffurls.push_back(crx_diffurl); - } - - // Expect at least one url for full update. - if (result->crx_urls.empty()) { - *error = "Missing valid url for full update."; - return false; - } - - return true; -} - -// Parses the <actions> tag. It picks up the "run" attribute of the first -// "action" element in "actions". -void ParseActionsTag(xmlNode* updatecheck, ProtocolParser::Result* result) { - std::vector<xmlNode*> actions = GetChildren(updatecheck, "actions"); - if (actions.empty()) - return; - - std::vector<xmlNode*> action = GetChildren(actions.front(), "action"); - if (action.empty()) - return; - - result->action_run = GetAttribute(action.front(), "run"); -} - -// Parses the <updatecheck> tag. -bool ParseUpdateCheckTag(xmlNode* updatecheck, - ProtocolParser::Result* result, - std::string* error) { - // Read the |status| attribute. - result->status = GetAttribute(updatecheck, "status"); - if (result->status.empty()) { - *error = "Missing status on updatecheck node"; - return false; - } - - if (result->status == "noupdate") { - ParseActionsTag(updatecheck, result); - return true; - } - - if (result->status == "ok") { - std::vector<xmlNode*> urls = GetChildren(updatecheck, "urls"); - if (urls.empty()) { - *error = "Missing urls on updatecheck."; - return false; - } - - if (!ParseUrlsTag(urls[0], result, error)) { - return false; - } - - std::vector<xmlNode*> manifests = GetChildren(updatecheck, "manifest"); - if (manifests.empty()) { - *error = "Missing manifest on updatecheck."; - return false; - } - - ParseActionsTag(updatecheck, result); - return ParseManifestTag(manifests[0], result, error); - } - - // Return the |updatecheck| element status as a parsing error. - *error = result->status; - return false; -} - -// Parses a single <app> tag. -bool ParseAppTag(xmlNode* app, - ProtocolParser::Result* result, - std::string* error) { - // Read cohort information. - auto cohort = GetAttributePtr(app, "cohort"); - static const char* attrs[] = {ProtocolParser::Result::kCohort, - ProtocolParser::Result::kCohortHint, - ProtocolParser::Result::kCohortName}; - for (auto* attr : attrs) { - auto value = GetAttributePtr(app, attr); - if (value) - result->cohort_attrs.insert({attr, *value}); - } - - // Read the crx id. - result->extension_id = GetAttribute(app, "appid"); - if (result->extension_id.empty()) { - *error = "Missing appid on app node"; - return false; - } - - // Read the |status| attribute for the app. - // If the status is one of the defined app status error literals, then return - // it in the result as if it were an updatecheck status, then stop parsing, - // and return success. - result->status = GetAttribute(app, "status"); - if (result->status == "restricted" || - result->status == "error-unknownApplication" || - result->status == "error-invalidAppId") - return true; - - // If the status was not handled above and the status is not "ok", then - // this must be a status literal that that the parser does not know about. - if (!result->status.empty() && result->status != "ok") { - *error = "Unknown app status"; - return false; - } - - // Get the <updatecheck> tag. - DCHECK(result->status.empty() || result->status == "ok"); - std::vector<xmlNode*> updates = GetChildren(app, "updatecheck"); - if (updates.empty()) { - *error = "Missing updatecheck on app."; - return false; - } - - return ParseUpdateCheckTag(updates[0], result, error); -} - -// An update response looks like this: -// -// <?xml version="1.0" encoding="UTF-8"?> -// <response protocol="3.0" server="prod"> -// <daystart elapsed_seconds="56508"/> -// <app appid="{430FD4D0-B729-4F61-AA34-91526481799D}" status="ok"> -// <updatecheck status="noupdate"/> -// <ping status="ok"/> -// </app> -// <app appid="{D0AB2EBC-931B-4013-9FEB-C9C4C2225C8C}" status="ok"> -// <updatecheck status="ok"> -// <urls> -// <url codebase="http://host/edgedl/chrome/install/782.112/" -// <url codebasediff="http://fallback/chrome/diff/782.112/"/> -// </urls> -// <manifest version="13.0.782.112" prodversionmin="2.0.143.0"> -// <packages> -// <package name="component.crx" -// namediff="diff_1.2.3.4.crx" -// fp="1.123" -// hash_sha256="9830b4245c4..." size="23963192" -// hashdiff_sha256="cfb6caf3d0..." sizediff="101"/> -// </packages> -// </manifest> -// </updatecheck> -// <ping status="ok"/> -// </app> -// </response> -// -// The <daystart> tag contains a "elapsed_seconds" attribute which refers to -// the server's notion of how many seconds it has been since midnight. -// -// The "appid" attribute of the <app> tag refers to the unique id of the -// extension. The "codebase" attribute of the <updatecheck> tag is the url to -// fetch the updated crx file, and the "prodversionmin" attribute refers to -// the minimum version of the chrome browser that the update applies to. -// -// The diff data members correspond to the differential update package, if -// a differential update is specified in the response. -bool ProtocolParserXml::DoParse(const std::string& response_xml, - Results* results) { - DCHECK(results); - - if (response_xml.empty()) { - ParseError("Empty xml"); - return false; - } - - std::string xml_errors; - ScopedXmlErrorFunc error_func(&xml_errors, &XmlErrorFunc); - - // Start up the xml parser with the manifest_xml contents. - ScopedXmlDocument document( - xmlParseDoc(reinterpret_cast<const xmlChar*>(response_xml.c_str()))); - if (!document.get()) { - ParseError("%s", xml_errors.c_str()); - return false; - } - - xmlNode* root = xmlDocGetRootElement(document.get()); - if (!root) { - ParseError("Missing root node"); - return false; - } - - if (!TagNameEquals(root, "response")) { - ParseError("Missing response tag"); - return false; - } - - // Check for the response "protocol" attribute. - const auto protocol = GetAttribute(root, "protocol"); - if (protocol != kProtocolVersion) { - ParseError( - "Missing/incorrect protocol on response tag " - "(expected '%s', found '%s')", - kProtocolVersion, protocol.c_str()); - return false; - } - - // Parse the first <daystart> if it is present. - std::vector<xmlNode*> daystarts = GetChildren(root, "daystart"); - if (!daystarts.empty()) { - xmlNode* first = daystarts[0]; - std::string elapsed_seconds = GetAttribute(first, "elapsed_seconds"); - int parsed_elapsed = kNoDaystart; - if (base::StringToInt(elapsed_seconds, &parsed_elapsed)) - results->daystart_elapsed_seconds = parsed_elapsed; - std::string elapsed_days = GetAttribute(first, "elapsed_days"); - parsed_elapsed = kNoDaystart; - if (base::StringToInt(elapsed_days, &parsed_elapsed)) - results->daystart_elapsed_days = parsed_elapsed; - } - - // Parse each of the <app> tags. - std::vector<xmlNode*> apps = GetChildren(root, "app"); - for (size_t i = 0; i != apps.size(); ++i) { - Result result; - std::string error; - if (ParseAppTag(apps[i], &result, &error)) - results->list.push_back(result); - else - ParseError("%s", error.c_str()); - } - - return true; -} - -} // namespace update_client
diff --git a/components/update_client/protocol_parser_xml.h b/components/update_client/protocol_parser_xml.h deleted file mode 100644 index 773ac96..0000000 --- a/components/update_client/protocol_parser_xml.h +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_UPDATE_CLIENT_PROTOCOL_PARSER_XML_H_ -#define COMPONENTS_UPDATE_CLIENT_PROTOCOL_PARSER_XML_H_ - -#include <string> - -#include "base/macros.h" -#include "components/update_client/protocol_parser.h" - -namespace update_client { - -// Parses responses for the update protocol version 3. -// (https://github.com/google/omaha/blob/wiki/ServerProtocolV3.md) -class ProtocolParserXml final : public ProtocolParser { - public: - ProtocolParserXml() = default; - - private: - // Overrides for ProtocolParser. - bool DoParse(const std::string& response_xml, Results* results) override; - - DISALLOW_COPY_AND_ASSIGN(ProtocolParserXml); -}; - -} // namespace update_client - -#endif // COMPONENTS_UPDATE_CLIENT_PROTOCOL_PARSER_XML_H_
diff --git a/components/update_client/protocol_parser_xml_unittest.cc b/components/update_client/protocol_parser_xml_unittest.cc deleted file mode 100644 index 28f2b71..0000000 --- a/components/update_client/protocol_parser_xml_unittest.cc +++ /dev/null
@@ -1,489 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/update_client/protocol_parser_xml.h" - -#include <memory> - -#include "testing/gtest/include/gtest/gtest.h" - -namespace update_client { - -const char* kValidXml = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response protocol='3.1'>" - " <app appid='12345'>" - " <updatecheck status='ok'>" - " <urls>" - " <url codebase='http://example.com/'/>" - " <url codebasediff='http://diff.example.com/'/>" - " </urls>" - " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" - " <packages>" - " <package name='extension_1_2_3_4.crx'/>" - " </packages>" - " </manifest>" - " </updatecheck>" - " </app>" - "</response>"; - -const char* valid_xml_with_hash = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response protocol='3.1'>" - " <app appid='12345'>" - " <updatecheck status='ok'>" - " <urls>" - " <url codebase='http://example.com/'/>" - " </urls>" - " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" - " <packages>" - " <package name='extension_1_2_3_4.crx' hash_sha256='1234'" - " hashdiff_sha256='5678'/>" - " </packages>" - " </manifest>" - " </updatecheck>" - " </app>" - "</response>"; - -const char* valid_xml_with_invalid_sizes = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response protocol='3.1'>" - " <app appid='12345'>" - " <updatecheck status='ok'>" - " <urls>" - " <url codebase='http://example.com/'/>" - " </urls>" - " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" - " <packages>" - " <package name='1' size='1234'/>" - " <package name='2' size='9223372036854775807'/>" - " <package name='3' size='-1234'/>" - " <package name='4' />" - " <package name='5' size='-a'/>" - " <package name='6' size='-123467890123456789'/>" - " <package name='7' size='123467890123456789012'/>" - " <package name='8' sizediff='1234'/>" - " <package name='9' sizediff='9223372036854775807'/>" - " <package name='10' sizediff='-1234'/>" - " <package name='11' sizediff='-a'/>" - " <package name='12' sizediff='-123467890123456789'/>" - " <package name='13' sizediff='123467890123456789012'/>" - " </packages>" - " </manifest>" - " </updatecheck>" - " </app>" - "</response>"; - -const char* kInvalidValidXmlMissingCodebase = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response protocol='3.1'>" - " <app appid='12345'>" - " <updatecheck status='ok'>" - " <urls>" - " <url codebasediff='http://diff.example.com/'/>" - " </urls>" - " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" - " <packages>" - " <package namediff='extension_1_2_3_4.crx'/>" - " </packages>" - " </manifest>" - " </updatecheck>" - " </app>" - "</response>"; - -const char* kInvalidValidXmlMissingManifest = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response protocol='3.1'>" - " <app appid='12345'>" - " <updatecheck status='ok'>" - " <urls>" - " <url codebase='http://example.com/'/>" - " </urls>" - " </updatecheck>" - " </app>" - "</response>"; - -const char* kMissingAppId = - "<?xml version='1.0'?>" - "<response protocol='3.1'>" - " <app>" - " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'" - " version='1.2.3.4'/>" - " </app>" - "</response>"; - -const char* kInvalidCodebase = - "<?xml version='1.0'?>" - "<response protocol='3.1'>" - " <app appid='12345' status='ok'>" - " <updatecheck codebase='example.com/extension_1.2.3.4.crx'" - " version='1.2.3.4'/>" - " </app>" - "</response>"; - -const char* kMissingVersion = - "<?xml version='1.0'?>" - "<response protocol='3.1'>" - " <app appid='12345' status='ok'>" - " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx'/>" - " </app>" - "</response>"; - -const char* kInvalidVersion = - "<?xml version='1.0'?>" - "<response protocol='3.1'>" - " <app appid='12345' status='ok'>" - " <updatecheck codebase='http://example.com/extension_1.2.3.4.crx' " - " version='1.2.3.a'/>" - " </app>" - "</response>"; - -// The v3 version of the protocol is not using namespaces. However, the parser -// must be able to parse responses that include namespaces. -const char* kUsesNamespacePrefix = - "<?xml version='1.0' encoding='UTF-8'?>" - "<g:response xmlns:g='http://www.google.com/update2/response' " - "protocol='3.1'>" - " <g:app appid='12345'>" - " <g:updatecheck status='ok'>" - " <g:urls>" - " <g:url codebase='http://example.com/'/>" - " </g:urls>" - " <g:manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" - " <g:packages>" - " <g:package name='extension_1_2_3_4.crx'/>" - " </g:packages>" - " </g:manifest>" - " </g:updatecheck>" - " </g:app>" - "</g:response>"; - -// Includes unrelated <app> tags from other xml namespaces - this should -// not cause problems. -const char* kSimilarTagnames = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response xmlns:a='http://a' protocol='3.1'>" - " <a:app appid='12345'>" - " <updatecheck status='ok'>" - " <urls>" - " <url codebase='http://example.com/'/>" - " </urls>" - " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" - " <packages>" - " <package name='extension_1_2_3_4.crx'/>" - " </packages>" - " </manifest>" - " </updatecheck>" - " </a:app>" - " <b:app appid='xyz' xmlns:b='http://b'>" - " <updatecheck status='noupdate'/>" - " </b:app>" - "</response>"; - -// Includes a <daystart> tag. -const char* kWithDaystart = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response protocol='3.1'>" - " <daystart elapsed_seconds='456'/>" - " <app appid='12345'>" - " <updatecheck status='ok'>" - " <urls>" - " <url codebase='http://example.com/'/>" - " </urls>" - " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" - " <packages>" - " <package name='extension_1_2_3_4.crx'/>" - " </packages>" - " </manifest>" - " </updatecheck>" - " </app>" - "</response>"; - -// Indicates no updates available - this should not be a parse error. -const char* kNoUpdate = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response protocol='3.1'>" - " <app appid='12345'>" - " <updatecheck status='noupdate'/>" - " </app>" - "</response>"; - -// Includes two <app> tags, one with an error. -const char* kTwoAppsOneError = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response protocol='3.1'>" - " <app appid='aaaaaaaa' status='error-unknownApplication'>" - " <updatecheck status='error-internal'/>" - " </app>" - " <app appid='bbbbbbbb'>" - " <updatecheck status='ok'>" - " <urls>" - " <url codebase='http://example.com/'/>" - " </urls>" - " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" - " <packages>" - " <package name='extension_1_2_3_4.crx'/>" - " </packages>" - " </manifest>" - " </updatecheck>" - " </app>" - "</response>"; - -// Includes two <app> tags, both of which set the cohort. -const char* kTwoAppsSetCohort = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response protocol='3.1'>" - " <app appid='aaaaaaaa' cohort='1:2q3/'>" - " <updatecheck status='noupdate'/>" - " </app>" - " <app appid='bbbbbbbb' cohort='1:33z@0.33' cohortname='cname'>" - " <updatecheck status='ok'>" - " <urls>" - " <url codebase='http://example.com/'/>" - " </urls>" - " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" - " <packages>" - " <package name='extension_1_2_3_4.crx'/>" - " </packages>" - " </manifest>" - " </updatecheck>" - " </app>" - "</response>"; - -// Includes a run action for an update check with status='ok'. -const char* kUpdateCheckStatusOkWithRunAction = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response protocol='3.1'>" - " <app appid='12345'>" - " <updatecheck status='ok'>" - " <urls>" - " <url codebase='http://example.com/'/>" - " <url codebasediff='http://diff.example.com/'/>" - " </urls>" - " <manifest version='1.2.3.4' prodversionmin='2.0.143.0'>" - " <packages>" - " <package name='extension_1_2_3_4.crx'/>" - " </packages>" - " </manifest>" - " <actions>" - " <action run='this'/>" - " </actions>" - " </updatecheck>" - " </app>" - "</response>"; - -// Includes a run action for an update check with status='noupdate'. -const char* kUpdateCheckStatusNoUpdateWithRunAction = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response protocol='3.1'>" - " <app appid='12345'>" - " <updatecheck status='noupdate'>" - " <actions>" - " <action run='this'/>" - " </actions>" - " </updatecheck>" - " </app>" - "</response>"; - -// Includes a run action for an update check with status='error'. -const char* kUpdateCheckStatusErrorWithRunAction = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response protocol='3.1'>" - " <app appid='12345' status='ok'>" - " <updatecheck status='error-osnotsupported'>" - " <actions>" - " <action run='this'/>" - " </actions>" - " </updatecheck>" - " </app>" - "</response>"; - -// Includes four <app> tags with status different than "ok". -const char* kAppsStatusError = - "<?xml version='1.0' encoding='UTF-8'?>" - "<response protocol='3.1'>" - " <app appid='aaaaaaaa' status='error-unknownApplication'>" - " <updatecheck status='error-internal'/>" - " </app>" - " <app appid='bbbbbbbb' status='restricted'>" - " <updatecheck status='error-internal'/>" - " </app>" - " <app appid='cccccccc' status='error-invalidAppId'>" - " <updatecheck status='error-internal'/>" - " </app>" - " <app appid='dddddddd' status='foobar'>" - " <updatecheck status='error-internal'/>" - " </app>" - "</response>"; - -TEST(UpdateClientProtocolParserXmlTest, Parse) { - const auto parser = std::make_unique<ProtocolParserXml>(); - - // Test parsing of a number of invalid xml cases - EXPECT_FALSE(parser->Parse(std::string())); - EXPECT_FALSE(parser->errors().empty()); - - EXPECT_TRUE(parser->Parse(kMissingAppId)); - EXPECT_TRUE(parser->results().list.empty()); - EXPECT_FALSE(parser->errors().empty()); - - EXPECT_TRUE(parser->Parse(kInvalidCodebase)); - EXPECT_TRUE(parser->results().list.empty()); - EXPECT_FALSE(parser->errors().empty()); - - EXPECT_TRUE(parser->Parse(kMissingVersion)); - EXPECT_TRUE(parser->results().list.empty()); - EXPECT_FALSE(parser->errors().empty()); - - EXPECT_TRUE(parser->Parse(kInvalidVersion)); - EXPECT_TRUE(parser->results().list.empty()); - EXPECT_FALSE(parser->errors().empty()); - - EXPECT_TRUE(parser->Parse(kInvalidValidXmlMissingCodebase)); - EXPECT_TRUE(parser->results().list.empty()); - EXPECT_FALSE(parser->errors().empty()); - - EXPECT_TRUE(parser->Parse(kInvalidValidXmlMissingManifest)); - EXPECT_TRUE(parser->results().list.empty()); - EXPECT_FALSE(parser->errors().empty()); - - // Parse some valid XML, and check that all params came out as expected - EXPECT_TRUE(parser->Parse(kValidXml)); - EXPECT_TRUE(parser->errors().empty()); - EXPECT_EQ(1u, parser->results().list.size()); - const ProtocolParser::Result* first_result = &parser->results().list[0]; - EXPECT_STREQ("ok", first_result->status.c_str()); - EXPECT_EQ(1u, first_result->crx_urls.size()); - EXPECT_EQ(GURL("http://example.com/"), first_result->crx_urls[0]); - EXPECT_EQ(GURL("http://diff.example.com/"), first_result->crx_diffurls[0]); - EXPECT_EQ("1.2.3.4", first_result->manifest.version); - EXPECT_EQ("2.0.143.0", first_result->manifest.browser_min_version); - EXPECT_EQ(1u, first_result->manifest.packages.size()); - EXPECT_EQ("extension_1_2_3_4.crx", first_result->manifest.packages[0].name); - - // Parse some xml that uses namespace prefixes. - EXPECT_TRUE(parser->Parse(kUsesNamespacePrefix)); - EXPECT_TRUE(parser->errors().empty()); - EXPECT_TRUE(parser->Parse(kSimilarTagnames)); - EXPECT_TRUE(parser->errors().empty()); - - // Parse xml with hash value - EXPECT_TRUE(parser->Parse(valid_xml_with_hash)); - EXPECT_TRUE(parser->errors().empty()); - EXPECT_FALSE(parser->results().list.empty()); - first_result = &parser->results().list[0]; - EXPECT_FALSE(first_result->manifest.packages.empty()); - EXPECT_EQ("1234", first_result->manifest.packages[0].hash_sha256); - EXPECT_EQ("5678", first_result->manifest.packages[0].hashdiff_sha256); - - // Parse xml with package size value - EXPECT_TRUE(parser->Parse(valid_xml_with_invalid_sizes)); - EXPECT_TRUE(parser->errors().empty()); - EXPECT_FALSE(parser->results().list.empty()); - first_result = &parser->results().list[0]; - EXPECT_FALSE(first_result->manifest.packages.empty()); - EXPECT_EQ(1234, first_result->manifest.packages[0].size); - EXPECT_EQ(9223372036854775807, first_result->manifest.packages[1].size); - EXPECT_EQ(0, first_result->manifest.packages[2].size); - EXPECT_EQ(0, first_result->manifest.packages[3].size); - EXPECT_EQ(0, first_result->manifest.packages[4].size); - EXPECT_EQ(0, first_result->manifest.packages[5].size); - EXPECT_EQ(0, first_result->manifest.packages[5].size); - EXPECT_EQ(1234, first_result->manifest.packages[7].sizediff); - EXPECT_EQ(9223372036854775807, first_result->manifest.packages[8].sizediff); - EXPECT_EQ(0, first_result->manifest.packages[9].sizediff); - EXPECT_EQ(0, first_result->manifest.packages[10].sizediff); - EXPECT_EQ(0, first_result->manifest.packages[11].sizediff); - EXPECT_EQ(0, first_result->manifest.packages[12].sizediff); - - // Parse xml with a <daystart> element. - EXPECT_TRUE(parser->Parse(kWithDaystart)); - EXPECT_TRUE(parser->errors().empty()); - EXPECT_FALSE(parser->results().list.empty()); - EXPECT_EQ(parser->results().daystart_elapsed_seconds, 456); - - // Parse a no-update response. - EXPECT_TRUE(parser->Parse(kNoUpdate)); - EXPECT_TRUE(parser->errors().empty()); - EXPECT_FALSE(parser->results().list.empty()); - first_result = &parser->results().list[0]; - EXPECT_STREQ("noupdate", first_result->status.c_str()); - EXPECT_EQ(first_result->extension_id, "12345"); - EXPECT_EQ(first_result->manifest.version, ""); - - // Parse xml with one error and one success <app> tag. - EXPECT_TRUE(parser->Parse(kTwoAppsOneError)); - EXPECT_TRUE(parser->errors().empty()); - EXPECT_EQ(2u, parser->results().list.size()); - first_result = &parser->results().list[0]; - EXPECT_EQ(first_result->extension_id, "aaaaaaaa"); - EXPECT_STREQ("error-unknownApplication", first_result->status.c_str()); - EXPECT_TRUE(first_result->manifest.version.empty()); - const ProtocolParser::Result* second_result = &parser->results().list[1]; - EXPECT_EQ(second_result->extension_id, "bbbbbbbb"); - EXPECT_STREQ("ok", second_result->status.c_str()); - EXPECT_EQ("1.2.3.4", second_result->manifest.version); - - // Parse xml with two apps setting the cohort info. - EXPECT_TRUE(parser->Parse(kTwoAppsSetCohort)); - EXPECT_TRUE(parser->errors().empty()); - EXPECT_EQ(2u, parser->results().list.size()); - first_result = &parser->results().list[0]; - EXPECT_EQ(first_result->extension_id, "aaaaaaaa"); - EXPECT_NE(first_result->cohort_attrs.find("cohort"), - first_result->cohort_attrs.end()); - EXPECT_EQ(first_result->cohort_attrs.find("cohort")->second, "1:2q3/"); - EXPECT_EQ(first_result->cohort_attrs.find("cohortname"), - first_result->cohort_attrs.end()); - EXPECT_EQ(first_result->cohort_attrs.find("cohorthint"), - first_result->cohort_attrs.end()); - second_result = &parser->results().list[1]; - EXPECT_EQ(second_result->extension_id, "bbbbbbbb"); - EXPECT_NE(second_result->cohort_attrs.find("cohort"), - second_result->cohort_attrs.end()); - EXPECT_EQ(second_result->cohort_attrs.find("cohort")->second, "1:33z@0.33"); - EXPECT_NE(second_result->cohort_attrs.find("cohortname"), - second_result->cohort_attrs.end()); - EXPECT_EQ(second_result->cohort_attrs.find("cohortname")->second, "cname"); - EXPECT_EQ(second_result->cohort_attrs.find("cohorthint"), - second_result->cohort_attrs.end()); - - EXPECT_TRUE(parser->Parse(kUpdateCheckStatusOkWithRunAction)); - EXPECT_TRUE(parser->errors().empty()); - EXPECT_FALSE(parser->results().list.empty()); - first_result = &parser->results().list[0]; - EXPECT_STREQ("ok", first_result->status.c_str()); - EXPECT_EQ(first_result->extension_id, "12345"); - EXPECT_STREQ("this", first_result->action_run.c_str()); - - EXPECT_TRUE(parser->Parse(kUpdateCheckStatusNoUpdateWithRunAction)); - EXPECT_TRUE(parser->errors().empty()); - EXPECT_FALSE(parser->results().list.empty()); - first_result = &parser->results().list[0]; - EXPECT_STREQ("noupdate", first_result->status.c_str()); - EXPECT_EQ(first_result->extension_id, "12345"); - EXPECT_STREQ("this", first_result->action_run.c_str()); - - EXPECT_TRUE(parser->Parse(kUpdateCheckStatusErrorWithRunAction)); - EXPECT_FALSE(parser->errors().empty()); - EXPECT_TRUE(parser->results().list.empty()); - - EXPECT_TRUE(parser->Parse(kAppsStatusError)); - EXPECT_STREQ("Unknown app status", parser->errors().c_str()); - EXPECT_EQ(3u, parser->results().list.size()); - first_result = &parser->results().list[0]; - EXPECT_EQ(first_result->extension_id, "aaaaaaaa"); - EXPECT_STREQ("error-unknownApplication", first_result->status.c_str()); - EXPECT_TRUE(first_result->manifest.version.empty()); - second_result = &parser->results().list[1]; - EXPECT_EQ(second_result->extension_id, "bbbbbbbb"); - EXPECT_STREQ("restricted", second_result->status.c_str()); - EXPECT_TRUE(second_result->manifest.version.empty()); - const ProtocolParser::Result* third_result = &parser->results().list[2]; - EXPECT_EQ(third_result->extension_id, "cccccccc"); - EXPECT_STREQ("error-invalidAppId", third_result->status.c_str()); - EXPECT_TRUE(third_result->manifest.version.empty()); -} - -} // namespace update_client
diff --git a/components/update_client/protocol_serializer_xml.cc b/components/update_client/protocol_serializer_xml.cc deleted file mode 100644 index 5cf61e4c..0000000 --- a/components/update_client/protocol_serializer_xml.cc +++ /dev/null
@@ -1,200 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/update_client/protocol_serializer_xml.h" - -#include <memory> - -#include "base/strings/stringprintf.h" -#include "base/values.h" -#include "build/build_config.h" -#include "components/update_client/updater_state.h" - -namespace update_client { - -std::string ProtocolSerializerXml::Serialize( - const protocol_request::Request& request) const { - std::string msg; - base::StringAppendF(&msg, - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" - "<request protocol=\"%s\"", - kProtocolVersion); - - // Constant information for this updater. - base::StringAppendF(&msg, " dedup=\"cr\" acceptformat=\"crx2,crx3\""); - - if (!request.additional_attributes.empty()) { - for (const auto& attr : request.additional_attributes) { - base::StringAppendF(&msg, " %s=\"%s\"", attr.first.c_str(), - attr.second.c_str()); - } - } - - // Session id and request id. - base::StringAppendF(&msg, " sessionid=\"%s\" requestid=\"%s\"", - request.session_id.c_str(), request.request_id.c_str()); - - // Chrome version and platform information. - base::StringAppendF(&msg, - " updater=\"%s\" updaterversion=\"%s\" prodversion=\"%s\"" - " lang=\"%s\" os=\"%s\" arch=\"%s\" nacl_arch=\"%s\"", - request.updatername.c_str(), - request.updaterversion.c_str(), - request.prodversion.c_str(), request.lang.c_str(), - request.operating_system.c_str(), request.arch.c_str(), - request.nacl_arch.c_str()); -#if defined(OS_WIN) - if (request.is_wow64) - base::StringAppendF(&msg, " wow64=\"%d\"", request.is_wow64); -#endif // OS_WIN - if (!request.updaterchannel.empty()) { - base::StringAppendF(&msg, " updaterchannel=\"%s\"", - request.updaterchannel.c_str()); - } - if (!request.prodchannel.empty()) { - base::StringAppendF(&msg, " prodchannel=\"%s\"", - request.prodchannel.c_str()); - } - if (!request.dlpref.empty()) - base::StringAppendF(&msg, " dlpref=\"%s\"", request.dlpref.c_str()); - - if (request.domain_joined) { - base::StringAppendF(&msg, " %s=\"%d\"", UpdaterState::kIsEnterpriseManaged, - *request.domain_joined); - } - base::StringAppendF(&msg, ">"); - - // HW platform information. - base::StringAppendF(&msg, "<hw physmemory=\"%d\"/>", request.hw.physmemory); - - // OS version and platform information. - base::StringAppendF(&msg, "<os platform=\"%s\" arch=\"%s\"", - request.os.platform.c_str(), request.os.arch.c_str()); - if (!request.os.version.empty()) - base::StringAppendF(&msg, " version=\"%s\"", request.os.version.c_str()); - if (!request.os.service_pack.empty()) - base::StringAppendF(&msg, " sp=\"%s\"", request.os.service_pack.c_str()); - base::StringAppendF(&msg, "/>"); - -#if defined(GOOGLE_CHROME_BUILD) - if (request.updater) { - const auto& updater = *request.updater; - base::StringAppendF(&msg, "<updater name=\"%s\"", updater.name.c_str()); - if (!updater.version.empty()) - base::StringAppendF(&msg, " version=\"%s\"", updater.version.c_str()); - if (updater.last_checked) - base::StringAppendF(&msg, " lastchecked=\"%d\"", *updater.last_checked); - if (updater.last_started) - base::StringAppendF(&msg, " laststarted=\"%d\"", *updater.last_started); - base::StringAppendF( - &msg, - " ismachine=\"%d\" autoupdatecheckenabled=\"%d\" updatepolicy=\"%d\"/>", - updater.is_machine, updater.autoupdate_check_enabled, - updater.update_policy); - } -#endif - - for (const auto& app : request.apps) { - // Begin <app> attributes. - base::StringAppendF(&msg, "<app appid=\"%s\"", app.app_id.c_str()); - base::StringAppendF(&msg, " version=\"%s\"", app.version.c_str()); - if (!app.brand_code.empty()) - base::StringAppendF(&msg, " brand=\"%s\"", app.brand_code.c_str()); - if (!app.install_source.empty()) { - base::StringAppendF(&msg, " installsource=\"%s\"", - app.install_source.c_str()); - } - if (!app.install_location.empty()) { - base::StringAppendF(&msg, " installedby=\"%s\"", - app.install_location.c_str()); - } - for (const auto& attr : app.installer_attributes) { - base::StringAppendF(&msg, " %s=\"%s\"", attr.first.c_str(), - attr.second.c_str()); - } - if (!app.cohort.empty()) - base::StringAppendF(&msg, " cohort=\"%s\"", app.cohort.c_str()); - if (!app.cohort_name.empty()) - base::StringAppendF(&msg, " cohortname=\"%s\"", app.cohort_name.c_str()); - if (!app.cohort_hint.empty()) - base::StringAppendF(&msg, " cohorthint=\"%s\"", app.cohort_hint.c_str()); - if (app.enabled) - base::StringAppendF(&msg, " enabled=\"%d\"", *app.enabled ? 1 : 0); - base::StringAppendF(&msg, ">"); - // End <app> attributes. - - if (app.disabled_reasons) { - for (const int disabled_reason : *app.disabled_reasons) - base::StringAppendF(&msg, "<disabled reason=\"%d\"/>", disabled_reason); - } - - if (app.update_check) { - base::StringAppendF(&msg, "<updatecheck"); - if (app.update_check->is_update_disabled) - base::StringAppendF(&msg, " updatedisabled=\"true\""); - base::StringAppendF(&msg, "/>"); - } - - if (app.ping) { - base::StringAppendF(&msg, "<ping"); - - // Output "ad" or "a" only if the this app has been seen 'active'. - if (app.ping->date_last_active) { - base::StringAppendF(&msg, " ad=\"%d\"", *app.ping->date_last_active); - } else if (app.ping->days_since_last_active_ping) { - base::StringAppendF(&msg, " a=\"%d\"", - *app.ping->days_since_last_active_ping); - } - - // Output "rd" if valid or "r" as a last resort roll call metric. - if (app.ping->date_last_roll_call) - base::StringAppendF(&msg, " rd=\"%d\"", *app.ping->date_last_roll_call); - else - base::StringAppendF(&msg, " r=\"%d\"", - app.ping->days_since_last_roll_call); - if (!app.ping->ping_freshness.empty()) - base::StringAppendF(&msg, " ping_freshness=\"%s\"", - app.ping->ping_freshness.c_str()); - - base::StringAppendF(&msg, "/>"); // End <ping>. - } - - if (!app.fingerprint.empty()) { - base::StringAppendF(&msg, - "<packages>" - "<package fp=\"%s\"/>" - "</packages>", - app.fingerprint.c_str()); - } - - if (app.events) { - for (const auto& event : *app.events) { - DCHECK(event.is_dict()); - DCHECK(!event.DictEmpty()); - base::StringAppendF(&msg, "<event"); - const auto& attrs = event.DictItems(); - for (auto it = attrs.begin(); it != attrs.end(); ++it) { - base::StringAppendF(&msg, " %s=", (*it).first.c_str()); - const auto& value = (*it).second; - if (value.is_string()) - base::StringAppendF(&msg, "\"%s\"", value.GetString().c_str()); - else if (value.is_int()) - base::StringAppendF(&msg, "\"%d\"", value.GetInt()); - else if (value.is_double()) - base::StringAppendF(&msg, "\"%.0f\"", value.GetDouble()); - else - NOTREACHED(); - } - base::StringAppendF(&msg, "/>"); - } - } - - base::StringAppendF(&msg, "</app>"); - } - - base::StringAppendF(&msg, "</request>"); - return msg; -} - -} // namespace update_client
diff --git a/components/update_client/protocol_serializer_xml.h b/components/update_client/protocol_serializer_xml.h deleted file mode 100644 index 48a47c2..0000000 --- a/components/update_client/protocol_serializer_xml.h +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_UPDATE_CLIENT_PROTOCOL_SERIALIZER_XML_H_ -#define COMPONENTS_UPDATE_CLIENT_PROTOCOL_SERIALIZER_XML_H_ - -#include <string> - -#include "components/update_client/protocol_serializer.h" - -namespace update_client { - -class ProtocolSerializerXml final : public ProtocolSerializer { - public: - ProtocolSerializerXml() = default; - - // Overrides for ProtocolSerializer. - std::string Serialize( - const protocol_request::Request& request) const override; - - private: - DISALLOW_COPY_AND_ASSIGN(ProtocolSerializerXml); -}; - -} // namespace update_client - -#endif // COMPONENTS_UPDATE_CLIENT_PROTOCOL_SERIALIZER_XML_H_
diff --git a/components/update_client/protocol_serializer_xml_unittest.cc b/components/update_client/protocol_serializer_xml_unittest.cc deleted file mode 100644 index 95bee49d..0000000 --- a/components/update_client/protocol_serializer_xml_unittest.cc +++ /dev/null
@@ -1,91 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <memory> -#include <string> - -#include "components/update_client/protocol_serializer.h" -#include "components/update_client/protocol_serializer_xml.h" -#include "components/update_client/updater_state.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/re2/src/re2/re2.h" - -using std::string; - -namespace update_client { - -TEST(SerializeRequestXml, Serialize) { - // When no updater state is provided, then check that the elements and - // attributes related to the updater state are not serialized. - const auto request = - std::make_unique<ProtocolSerializerXml>()->Serialize(MakeProtocolRequest( - "{15160585-8ADE-4D3C-839B-1281A6035D1F}", "prod_id", "1.0", "lang", - "channel", "OS", "cacheable", {{"extra", "params"}}, nullptr, {})); - constexpr char regex[] = - R"(<\?xml version="1\.0" encoding="UTF-8"\?>)" - R"(<request protocol="3\.1" )" - R"(dedup="cr" acceptformat="crx2,crx3" extra="params" )" - R"(sessionid="{[-\w]{36}}" requestid="{[-\w]{36}}" )" - R"(updater="prod_id" updaterversion="1\.0" prodversion="1\.0" )" - R"(lang="lang" os="\w+" arch="\w+" nacl_arch="[-\w]+" (wow64="1" )?)" - R"(updaterchannel="channel" prodchannel="channel" dlpref="cacheable">)" - R"(<hw physmemory="\d+"/>)" - R"(<os platform="OS" arch="[,-.\w]+" version="[-.\w]+"( sp="[\s\w]+")?/>)" - R"(</request>)"; - EXPECT_TRUE(RE2::FullMatch(request, regex)) << request; -} - -TEST(SerializeRequestXml, DownloadPreference) { - // Verifies that an empty |download_preference| is not serialized. - const auto serializer = std::make_unique<ProtocolSerializerXml>(); - auto request = serializer->Serialize( - MakeProtocolRequest("{15160585-8ADE-4D3C-839B-1281A6035D1F}", "", "", "", - "", "", "", {}, nullptr, {})); - EXPECT_FALSE(RE2::PartialMatch(request, " dlpref=")) << request; - - // Verifies that |download_preference| is serialized. - request = serializer->Serialize( - MakeProtocolRequest("{15160585-8ADE-4D3C-839B-1281A6035D1F}", "", "", "", - "", "", "cacheable", {}, nullptr, {})); - EXPECT_TRUE(RE2::PartialMatch(request, R"( dlpref="cacheable")")) << request; -} - -// When present, updater state attributes are only serialized for Google builds, -// except the |domainjoined| attribute, which is serialized in all cases. -TEST(SerializeRequestXml, UpdaterStateAttributes) { - const auto serializer = std::make_unique<ProtocolSerializerXml>(); - UpdaterState::Attributes attributes; - attributes["ismachine"] = "1"; - attributes["domainjoined"] = "1"; - attributes["name"] = "Omaha"; - attributes["version"] = "1.2.3.4"; - attributes["laststarted"] = "1"; - attributes["lastchecked"] = "2"; - attributes["autoupdatecheckenabled"] = "0"; - attributes["updatepolicy"] = "-1"; - const auto request = serializer->Serialize(MakeProtocolRequest( - "{15160585-8ADE-4D3C-839B-1281A6035D1F}", "prod_id", "1.0", "lang", - "channel", "OS", "cacheable", {{"extra", "params"}}, &attributes, {})); - constexpr char regex[] = - R"(<\?xml version="1\.0" encoding="UTF-8"\?>)" - R"(<request protocol="3\.1" )" - R"(dedup="cr" acceptformat="crx2,crx3" extra="params" )" - R"(sessionid="{[-\w]{36}}" requestid="{[-\w]{36}}" )" - R"(updater="prod_id" updaterversion="1\.0" prodversion="1\.0" )" - R"(lang="lang" os="\w+" arch="\w+" nacl_arch="[-\w]+" (wow64="1" )?)" - R"(updaterchannel="channel" prodchannel="channel" dlpref="cacheable" )" - R"(domainjoined="1">)" - R"(<hw physmemory="\d+"/>)" - R"(<os platform="OS" arch="[,-.\w]+" version="[-.\w]+"( sp="[\s\w]+")?/>)" -#if defined(GOOGLE_CHROME_BUILD) - R"(<updater name="Omaha" version="1\.2\.3\.4" lastchecked="2" )" - R"(laststarted="1" ismachine="1" autoupdatecheckenabled="0" )" - R"(updatepolicy="-1"/>)" -#endif // GOOGLE_CHROME_BUILD - R"(</request>)"; - - EXPECT_TRUE(RE2::FullMatch(request, regex)) << request; -} - -} // namespace update_client
diff --git a/components/update_client/request_sender_unittest.cc b/components/update_client/request_sender_unittest.cc index 7d5debbc..e1e16d8 100644 --- a/components/update_client/request_sender_unittest.cc +++ b/components/update_client/request_sender_unittest.cc
@@ -130,7 +130,7 @@ TEST_P(RequestSenderTest, RequestSendSuccess) { EXPECT_TRUE( post_interceptor_->ExpectRequest(std::make_unique<PartialMatch>("test"), - test_file("updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); const bool is_foreground = GetParam(); request_sender_->Send( @@ -154,10 +154,7 @@ // Check the response post conditions. EXPECT_EQ(0, error_); - EXPECT_TRUE(base::StartsWith(response_, - "<?xml version='1.0' encoding='UTF-8'?>", - base::CompareCase::SENSITIVE)); - EXPECT_EQ(505ul, response_.size()); + EXPECT_EQ(419ul, response_.size()); // Check the interactivity header value. const auto extra_request_headers = @@ -242,7 +239,7 @@ TEST_F(RequestSenderTest, RequestSendCupError) { EXPECT_TRUE( post_interceptor_->ExpectRequest(std::make_unique<PartialMatch>("test"), - test_file("updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); const std::vector<GURL> urls = {GURL(kUrl1)}; request_sender_ = std::make_unique<RequestSender>(config_);
diff --git a/components/update_client/test_configurator.cc b/components/update_client/test_configurator.cc index 7820f3b..2fc9e24a 100644 --- a/components/update_client/test_configurator.cc +++ b/components/update_client/test_configurator.cc
@@ -37,7 +37,6 @@ ondemand_time_(0), enabled_cup_signing_(false), enabled_component_updates_(true), - use_JSON_(false), connector_(connector_factory_.CreateConnector()), unzip_service_( connector_factory_.RegisterInstance(unzip::mojom::kServiceName)), @@ -183,10 +182,6 @@ app_guid_ = app_guid; } -void TestConfigurator::SetUseJSON(bool use_JSON) { - use_JSON_ = use_JSON; -} - PrefService* TestConfigurator::GetPrefService() const { return nullptr; } @@ -209,9 +204,7 @@ std::unique_ptr<ProtocolHandlerFactory> TestConfigurator::GetProtocolHandlerFactory() const { - if (use_JSON_) - return std::make_unique<ProtocolHandlerFactoryJSON>(); - return std::make_unique<ProtocolHandlerFactoryXml>(); + return std::make_unique<ProtocolHandlerFactoryJSON>(); } RecoveryCRXElevator TestConfigurator::GetRecoveryCRXElevator() const {
diff --git a/components/update_client/update_checker_unittest.cc b/components/update_client/update_checker_unittest.cc index c74a51f..ac4fa08a 100644 --- a/components/update_client/update_checker_unittest.cc +++ b/components/update_client/update_checker_unittest.cc
@@ -109,10 +109,7 @@ } // namespace -using UpdateCheckTestParams = - std::tuple<bool /*is_foreground*/, bool /*use_JSON*/>; - -class UpdateCheckerTest : public testing::TestWithParam<UpdateCheckTestParams> { +class UpdateCheckerTest : public testing::TestWithParam<bool> { public: UpdateCheckerTest(); ~UpdateCheckerTest() override; @@ -149,7 +146,6 @@ scoped_refptr<UpdateContext> update_context_; - bool use_JSON_ = false; bool is_foreground_ = false; private: @@ -161,10 +157,8 @@ DISALLOW_COPY_AND_ASSIGN(UpdateCheckerTest); }; -// This test is parameterized for |is_foreground and |use_JSON|. -INSTANTIATE_TEST_SUITE_P(Parameterized, - UpdateCheckerTest, - testing::Combine(testing::Bool(), testing::Bool())); +// This test is parameterized for |is_foreground|. +INSTANTIATE_TEST_SUITE_P(Parameterized, UpdateCheckerTest, testing::Bool()); UpdateCheckerTest::UpdateCheckerTest() : scoped_task_environment_( @@ -174,10 +168,9 @@ } void UpdateCheckerTest::SetUp() { - std::tie(is_foreground_, use_JSON_) = GetParam(); + is_foreground_ = GetParam(); config_ = base::MakeRefCounted<TestConfigurator>(); - config_->SetUseJSON(use_JSON_); pref_ = std::make_unique<TestingPrefServiceSimple>(); activity_data_service_ = std::make_unique<ActivityDataServiceTest>(); @@ -258,8 +251,7 @@ TEST_P(UpdateCheckerTest, UpdateCheckSuccess) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); @@ -282,55 +274,54 @@ << post_interceptor_->GetRequestsAsString(); // Sanity check the request. - const auto& request = post_interceptor_->GetRequestBody(0); - if (use_JSON_) { - const auto root = base::JSONReader::Read(request); - ASSERT_TRUE(root); - const auto* request = root->FindKey("request"); - ASSERT_TRUE(request); - EXPECT_TRUE(request->FindKey("@os")); - EXPECT_EQ("fake_prodid", request->FindKey("@updater")->GetString()); - EXPECT_EQ("crx2,crx3", request->FindKey("acceptformat")->GetString()); - EXPECT_TRUE(request->FindKey("arch")); - EXPECT_EQ("cr", request->FindKey("dedup")->GetString()); - EXPECT_EQ("params", request->FindKey("extra")->GetString()); - EXPECT_LT(0, request->FindPath({"hw", "physmemory"})->GetInt()); - EXPECT_EQ("fake_lang", request->FindKey("lang")->GetString()); - EXPECT_TRUE(request->FindKey("nacl_arch")); - EXPECT_EQ("fake_channel_string", - request->FindKey("prodchannel")->GetString()); - EXPECT_EQ("30.0", request->FindKey("prodversion")->GetString()); - EXPECT_EQ("3.1", request->FindKey("protocol")->GetString()); - EXPECT_TRUE(request->FindKey("requestid")); - EXPECT_TRUE(request->FindKey("sessionid")); - EXPECT_EQ("1", request->FindKey("testrequest")->GetString()); - EXPECT_EQ("fake_channel_string", - request->FindKey("updaterchannel")->GetString()); - EXPECT_EQ("30.0", request->FindKey("updaterversion")->GetString()); + const auto root = + base::JSONReader::Read(post_interceptor_->GetRequestBody(0)); + ASSERT_TRUE(root); + const auto* request = root->FindKey("request"); + ASSERT_TRUE(request); + EXPECT_TRUE(request->FindKey("@os")); + EXPECT_EQ("fake_prodid", request->FindKey("@updater")->GetString()); + EXPECT_EQ("crx2,crx3", request->FindKey("acceptformat")->GetString()); + EXPECT_TRUE(request->FindKey("arch")); + EXPECT_EQ("cr", request->FindKey("dedup")->GetString()); + EXPECT_EQ("params", request->FindKey("extra")->GetString()); + EXPECT_LT(0, request->FindPath({"hw", "physmemory"})->GetInt()); + EXPECT_EQ("fake_lang", request->FindKey("lang")->GetString()); + EXPECT_TRUE(request->FindKey("nacl_arch")); + EXPECT_EQ("fake_channel_string", + request->FindKey("prodchannel")->GetString()); + EXPECT_EQ("30.0", request->FindKey("prodversion")->GetString()); + EXPECT_EQ("3.1", request->FindKey("protocol")->GetString()); + EXPECT_TRUE(request->FindKey("requestid")); + EXPECT_TRUE(request->FindKey("sessionid")); + EXPECT_EQ("1", request->FindKey("testrequest")->GetString()); + EXPECT_EQ("fake_channel_string", + request->FindKey("updaterchannel")->GetString()); + EXPECT_EQ("30.0", request->FindKey("updaterversion")->GetString()); - // No "dlpref" is sent by default. - EXPECT_FALSE(request->FindKey("dlpref")); + // No "dlpref" is sent by default. + EXPECT_FALSE(request->FindKey("dlpref")); - EXPECT_TRUE(request->FindPath({"os", "arch"})->is_string()); - EXPECT_EQ("Fake Operating System", - request->FindPath({"os", "platform"})->GetString()); - EXPECT_TRUE(request->FindPath({"os", "version"})->is_string()); + EXPECT_TRUE(request->FindPath({"os", "arch"})->is_string()); + EXPECT_EQ("Fake Operating System", + request->FindPath({"os", "platform"})->GetString()); + EXPECT_TRUE(request->FindPath({"os", "version"})->is_string()); - const auto& app = request->FindKey("app")->GetList()[0]; - EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); - EXPECT_EQ("0.9", app.FindKey("version")->GetString()); - EXPECT_EQ("TEST", app.FindKey("brand")->GetString()); - if (is_foreground_) - EXPECT_EQ("ondemand", app.FindKey("installsource")->GetString()); - EXPECT_EQ("some_ap", app.FindKey("ap")->GetString()); - EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); - EXPECT_TRUE(app.FindKey("updatecheck")); - EXPECT_TRUE(app.FindKey("ping")); - EXPECT_EQ(-2, app.FindPath({"ping", "r"})->GetInt()); - EXPECT_EQ("fp1", app.FindPath({"packages", "package"}) - ->GetList()[0] - .FindKey("fp") - ->GetString()); + const auto& app = request->FindKey("app")->GetList()[0]; + EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.9", app.FindKey("version")->GetString()); + EXPECT_EQ("TEST", app.FindKey("brand")->GetString()); + if (is_foreground_) + EXPECT_EQ("ondemand", app.FindKey("installsource")->GetString()); + EXPECT_EQ("some_ap", app.FindKey("ap")->GetString()); + EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); + EXPECT_TRUE(app.FindKey("updatecheck")); + EXPECT_TRUE(app.FindKey("ping")); + EXPECT_EQ(-2, app.FindPath({"ping", "r"})->GetInt()); + EXPECT_EQ("fp1", app.FindPath({"packages", "package"}) + ->GetList()[0] + .FindKey("fp") + ->GetString()); #if (OS_WIN) EXPECT_TRUE(request->FindKey("domainjoined")); @@ -343,40 +334,6 @@ EXPECT_TRUE(updater->FindKey("updatepolicy")->is_int()); #endif // GOOGLE_CHROME_BUILD #endif // OS_WINDOWS - } else { - EXPECT_THAT(request, testing::HasSubstr( - R"(request protocol="3.1" dedup="cr" )" - R"(acceptformat="crx2,crx3" extra="params" )" - R"(testrequest="1")")); - // The request must not contain any "dlpref" in the default case. - EXPECT_THAT(request, testing::Not(testing::HasSubstr(R"( dlpref=")"))); - EXPECT_THAT( - request, - testing::HasSubstr( - std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" brand="TEST")" + - (is_foreground_ ? R"( installsource="ondemand")" : "") + - R"( ap="some_ap" enabled="1"><updatecheck/><ping r="-2"/>)")); - EXPECT_THAT(request, - testing::HasSubstr( - R"(<packages><package fp="fp1"/></packages></app>)")); - EXPECT_THAT(request, testing::HasSubstr("<hw physmemory=")); - - // Tests that the product id is injected correctly from the configurator. - EXPECT_THAT(request, testing::HasSubstr( - R"( updater="fake_prodid" updaterversion="30.0")" - R"( prodversion="30.0" )")); - // Tests that there is a sessionid attribute. - EXPECT_THAT(request, testing::HasSubstr(" sessionid=")); -#if (OS_WIN) - EXPECT_THAT(request, testing::HasSubstr(" domainjoined=")); -#if defined(GOOGLE_CHROME_BUILD) - // Check the Omaha updater state data in the request. - EXPECT_THAT(request, testing::HasSubstr("<updater ")); - EXPECT_THAT(request, testing::HasSubstr(R"( name="Omaha" )")); -#endif // GOOGLE_CHROME_BUILD -#endif // OS_WINDOWS - } // Sanity check the arguments of the callback after parsing. EXPECT_EQ(ErrorCategory::kNone, error_category_); @@ -411,8 +368,7 @@ TEST_P(UpdateCheckerTest, UpdateCheckInvalidAp) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); @@ -431,7 +387,6 @@ RunThreads(); const auto request = post_interceptor_->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -449,30 +404,12 @@ ->GetList()[0] .FindKey("fp") ->GetString()); - } else { - if (is_foreground_) { - EXPECT_THAT(request, testing::HasSubstr( - std::string(R"(app appid=")") + kUpdateItemId + - R"(" version="0.9" brand="TEST" )" - R"(installsource="ondemand" enabled="1">)" - R"(<updatecheck/><ping r="-2"/>)")); - } else { - EXPECT_THAT(request, testing::HasSubstr( - std::string(R"(app appid=")") + kUpdateItemId + - R"(" version="0.9" brand="TEST" enabled="1">)" - R"(<updatecheck/><ping r="-2"/>)")); - } - EXPECT_THAT(request, - testing::HasSubstr( - R"(<packages><package fp="fp1"/></packages></app>)")); - } } TEST_P(UpdateCheckerTest, UpdateCheckSuccessNoBrand) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); config_->SetBrand("TOOLONG"); // Sets an invalid brand code. update_checker_ = UpdateChecker::Create(config_, metadata_.get()); @@ -489,7 +426,6 @@ const auto request = post_interceptor_->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -506,22 +442,6 @@ ->GetList()[0] .FindKey("fp") ->GetString()); - } else { - if (is_foreground_) { - EXPECT_THAT(request, testing::HasSubstr( - std::string(R"(app appid=")") + kUpdateItemId + - R"(" version="0.9" installsource="ondemand" )" - R"(enabled="1"><updatecheck/><ping r="-2"/>)")); - } else { - EXPECT_THAT(request, testing::HasSubstr( - std::string(R"(app appid=")") + kUpdateItemId + - R"(" version="0.9" enabled="1">)" + - R"(<updatecheck/><ping r="-2"/>)")); - } - EXPECT_THAT(request, - testing::HasSubstr( - R"(<packages><package fp="fp1"/></packages></app>)")); - } } // Simulates a 403 server response error. @@ -553,8 +473,7 @@ TEST_P(UpdateCheckerTest, UpdateCheckDownloadPreference) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); config_->SetDownloadPreference(string("cacheable")); @@ -572,14 +491,10 @@ // The request must contain dlpref="cacheable". const auto request = post_interceptor_->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader().Read(request); ASSERT_TRUE(root); EXPECT_EQ("cacheable", root->FindKey("request")->FindKey("dlpref")->GetString()); - } else { - EXPECT_THAT(request, testing::HasSubstr(R"( dlpref="cacheable")")); - } } // This test is checking that an update check signed with CUP fails, since there @@ -588,8 +503,7 @@ TEST_P(UpdateCheckerTest, UpdateCheckCupError) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); config_->SetEnabledCupSigning(true); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); @@ -611,7 +525,6 @@ // Sanity check the request. const auto& request = post_interceptor_->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -629,24 +542,6 @@ .FindKey("fp") ->GetString()); - } else { - if (is_foreground_) { - EXPECT_THAT(request, testing::HasSubstr( - std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" brand="TEST" )" - R"(installsource="ondemand" enabled="1">)" - R"(<updatecheck/><ping r="-2"/>)")); - } else { - EXPECT_THAT(request, testing::HasSubstr( - std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" brand="TEST" enabled="1">)" - R"(<updatecheck/><ping r="-2"/>)")); - } - EXPECT_THAT(request, - testing::HasSubstr( - R"(<packages><package fp="fp1"/></packages></app>)")); - } - // Expect an error since the response is not trusted. EXPECT_EQ(ErrorCategory::kUpdateCheck, error_category_); EXPECT_EQ(-10000, error_); @@ -680,8 +575,7 @@ // Tests that the PersistedData will get correctly update and reserialize // the elapsed_days value. TEST_P(UpdateCheckerTest, UpdateCheckLastRollCall) { - const char* filename = - use_JSON_ ? "updatecheck_reply_4.json" : "updatecheck_reply_4.xml"; + const char* filename = "updatecheck_reply_4.json"; EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), test_file(filename))); EXPECT_TRUE(post_interceptor_->ExpectRequest( @@ -714,7 +608,6 @@ ASSERT_EQ(2, post_interceptor_->GetCount()) << post_interceptor_->GetRequestsAsString(); - if (use_JSON_) { const auto root1 = base::JSONReader::Read(post_interceptor_->GetRequestBody(0)); ASSERT_TRUE(root1); @@ -726,17 +619,10 @@ const auto& app2 = root2->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(3383, app2.FindPath({"ping", "rd"})->GetInt()); EXPECT_TRUE(app2.FindPath({"ping", "ping_freshness"})->is_string()); - } else { - EXPECT_THAT(post_interceptor_->GetRequestBody(0), - testing::HasSubstr(R"(<ping r="5")")); - EXPECT_THAT(post_interceptor_->GetRequestBody(1), - testing::HasSubstr(R"(<ping rd="3383" ping_freshness=)")); - } } TEST_P(UpdateCheckerTest, UpdateCheckLastActive) { - const char* filename = - use_JSON_ ? "updatecheck_reply_4.json" : "updatecheck_reply_4.xml"; + const char* filename = "updatecheck_reply_4.json"; EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), test_file(filename))); EXPECT_TRUE(post_interceptor_->ExpectRequest( @@ -788,7 +674,6 @@ ASSERT_EQ(3, post_interceptor_->GetCount()) << post_interceptor_->GetRequestsAsString(); - if (use_JSON_) { { const auto root = base::JSONReader::Read(post_interceptor_->GetRequestBody(0)); @@ -814,15 +699,6 @@ EXPECT_EQ(3383, app.FindPath({"ping", "rd"})->GetInt()); EXPECT_TRUE(app.FindPath({"ping", "ping_freshness"})->is_string()); } - } else { - EXPECT_THAT(post_interceptor_->GetRequestBody(0), - testing::HasSubstr(R"(<ping a="10" r="-2"/>)")); - EXPECT_THAT( - post_interceptor_->GetRequestBody(1), - testing::HasSubstr(R"(<ping ad="3383" rd="3383" ping_freshness=)")); - EXPECT_THAT(post_interceptor_->GetRequestBody(2), - testing::HasSubstr(R"(<ping rd="3383" ping_freshness=)")); - } } TEST_P(UpdateCheckerTest, UpdateCheckInstallSource) { @@ -840,34 +716,26 @@ config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_->CheckForUpdates( update_context_->session_id, {kUpdateItemId}, components, {}, false, base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ("ondemand", app.FindKey("installsource")->GetString()); EXPECT_FALSE(app.FindKey("installedby")); - } else { - EXPECT_THAT(request, testing::HasSubstr(R"(installsource="ondemand")")); - EXPECT_THAT(request, - testing::Not(testing::HasSubstr(R"(installedby=)"))); - } } { auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); crx_component->install_source = "sideload"; crx_component->install_location = "policy"; component->set_crx_component(*crx_component); @@ -877,17 +745,12 @@ base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ("sideload", app.FindKey("installsource")->GetString()); EXPECT_EQ("policy", app.FindKey("installedby")->GetString()); - } else { - EXPECT_THAT(request, testing::HasSubstr(R"(installsource="sideload")")); - EXPECT_THAT(request, testing::HasSubstr(R"(installedby="policy")")); - } } return; } @@ -898,30 +761,24 @@ config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_->CheckForUpdates( update_context_->session_id, {kUpdateItemId}, components, {}, false, base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_FALSE(app.FindKey("installsource")); - } else { - EXPECT_THAT(request, testing::Not(testing::HasSubstr("installsource="))); - } } { auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); crx_component->install_source = "webstore"; crx_component->install_location = "external"; component->set_crx_component(*crx_component); @@ -931,16 +788,11 @@ base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ("webstore", app.FindKey("installsource")->GetString()); EXPECT_EQ("external", app.FindKey("installedby")->GetString()); - } else { - EXPECT_THAT(request, testing::HasSubstr(R"(installsource="webstore")")); - EXPECT_THAT(request, testing::HasSubstr(R"(installedby="external")")); - } } } @@ -958,24 +810,18 @@ config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_->CheckForUpdates( update_context_->session_id, {kUpdateItemId}, components, {}, false, base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); EXPECT_FALSE(app.FindKey("disabled")); - } else { - EXPECT_THAT(request, testing::HasSubstr(R"(enabled="1")")); - EXPECT_THAT(request, testing::Not(testing::HasSubstr("<disabled"))); - } } { @@ -985,24 +831,18 @@ config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_->CheckForUpdates( update_context_->session_id, {kUpdateItemId}, components, {}, false, base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); EXPECT_FALSE(app.FindKey("disabled")); - } else { - EXPECT_THAT(request, testing::HasSubstr(R"(enabled="1")")); - EXPECT_THAT(request, testing::Not(testing::HasSubstr("<disabled"))); - } } { @@ -1012,15 +852,13 @@ config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_->CheckForUpdates( update_context_->session_id, {kUpdateItemId}, components, {}, false, base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -1028,10 +866,6 @@ const auto& disabled = app.FindKey("disabled")->GetList(); EXPECT_EQ(1u, disabled.size()); EXPECT_EQ(0, disabled[0].FindKey("reason")->GetInt()); - } else { - EXPECT_THAT(request, testing::HasSubstr(R"(enabled="0")")); - EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="0")")); - } } { crx_component->disabled_reasons = {1}; @@ -1040,15 +874,13 @@ config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_->CheckForUpdates( update_context_->session_id, {kUpdateItemId}, components, {}, false, base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -1056,10 +888,6 @@ const auto& disabled = app.FindKey("disabled")->GetList(); EXPECT_EQ(1u, disabled.size()); EXPECT_EQ(1, disabled[0].FindKey("reason")->GetInt()); - } else { - EXPECT_THAT(request, testing::HasSubstr(R"(enabled="0")")); - EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="1")")); - } } { @@ -1069,15 +897,13 @@ config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_->CheckForUpdates( update_context_->session_id, {kUpdateItemId}, components, {}, false, base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -1087,12 +913,6 @@ EXPECT_EQ(4, disabled[0].FindKey("reason")->GetInt()); EXPECT_EQ(8, disabled[1].FindKey("reason")->GetInt()); EXPECT_EQ(16, disabled[2].FindKey("reason")->GetInt()); - } else { - EXPECT_THAT(request, testing::HasSubstr(R"(enabled="0")")); - EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="4")")); - EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="8")")); - EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="16")")); - } } { @@ -1102,15 +922,13 @@ config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_->CheckForUpdates( update_context_->session_id, {kUpdateItemId}, components, {}, false, base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -1121,13 +939,6 @@ EXPECT_EQ(4, disabled[1].FindKey("reason")->GetInt()); EXPECT_EQ(8, disabled[2].FindKey("reason")->GetInt()); EXPECT_EQ(16, disabled[3].FindKey("reason")->GetInt()); - } else { - EXPECT_THAT(request, testing::HasSubstr(R"(enabled="0")")); - EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="0")")); - EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="4")")); - EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="8")")); - EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="16")")); - } } } @@ -1154,15 +965,13 @@ config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_->CheckForUpdates( update_context_->session_id, {kUpdateItemId}, components, {}, false, base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -1170,12 +979,6 @@ EXPECT_EQ("0.9", app.FindKey("version")->GetString()); EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); EXPECT_TRUE(app.FindKey("updatecheck")->DictEmpty()); - } else { - EXPECT_THAT( - request, - testing::HasSubstr(std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" enabled="1"><updatecheck/>)")); - } } { // Tests the scenario where: @@ -1188,15 +991,13 @@ config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_->CheckForUpdates( update_context_->session_id, {kUpdateItemId}, components, {}, false, base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -1204,12 +1005,6 @@ EXPECT_EQ("0.9", app.FindKey("version")->GetString()); EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); EXPECT_TRUE(app.FindPath({"updatecheck", "updatedisabled"})->GetBool()); - } else { - EXPECT_THAT(request, testing::HasSubstr( - std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" enabled="1">)" + - R"(<updatecheck updatedisabled="true"/>)")); - } } { // Tests the scenario where: @@ -1222,15 +1017,13 @@ config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_->CheckForUpdates( update_context_->session_id, {kUpdateItemId}, components, {}, true, base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -1238,12 +1031,6 @@ EXPECT_EQ("0.9", app.FindKey("version")->GetString()); EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); EXPECT_TRUE(app.FindKey("updatecheck")->DictEmpty()); - } else { - EXPECT_THAT( - request, - testing::HasSubstr(std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" enabled="1"><updatecheck/>)")); - } } { // Tests the scenario where: @@ -1256,15 +1043,13 @@ config_->test_url_loader_factory()); EXPECT_TRUE(post_interceptor->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_1.json" - : "updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); update_checker_->CheckForUpdates( update_context_->session_id, {kUpdateItemId}, components, {}, true, base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, base::Unretained(this))); RunThreads(); const auto& request = post_interceptor->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -1272,20 +1057,13 @@ EXPECT_EQ("0.9", app.FindKey("version")->GetString()); EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); EXPECT_TRUE(app.FindKey("updatecheck")->DictEmpty()); - } else { - EXPECT_THAT( - request, - testing::HasSubstr(std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" enabled="1"><updatecheck/>)")); - } } } TEST_P(UpdateCheckerTest, NoUpdateActionRun) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_noupdate.json" - : "updatecheck_reply_noupdate.xml"))); + test_file("updatecheck_reply_noupdate.json"))); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); IdToComponentPtrMap components; @@ -1316,8 +1094,7 @@ TEST_P(UpdateCheckerTest, UpdatePauseResume) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_noupdate.json" - : "updatecheck_reply_noupdate.xml"))); + test_file("updatecheck_reply_noupdate.json"))); post_interceptor_->url_job_request_ready_callback(base::BindOnce( [](URLLoaderPostInterceptor* post_interceptor) { post_interceptor->Resume(); @@ -1340,7 +1117,6 @@ RunThreads(); const auto& request = post_interceptor_->GetRequestBody(0); - if (use_JSON_) { const auto root = base::JSONReader::Read(request); ASSERT_TRUE(root); const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; @@ -1355,15 +1131,6 @@ ->GetList()[0] .FindKey("fp") ->GetString()); - } else { - EXPECT_THAT(request, testing::HasSubstr( - std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" brand="TEST" enabled="1">)" + - R"(<updatecheck/><ping r="-2"/>)")); - EXPECT_THAT(request, - testing::HasSubstr( - R"(<packages><package fp="fp1"/></packages></app>)")); - } } // Tests that an update checker object and its underlying SimpleURLLoader can @@ -1374,7 +1141,7 @@ EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); + test_file("updatecheck_reply_1.json"))); post_interceptor_->url_job_request_ready_callback(base::BindOnce( [](base::OnceClosure quit_closure) { std::move(quit_closure).Run(); }, std::move(quit_closure))); @@ -1396,8 +1163,7 @@ TEST_P(UpdateCheckerTest, ParseErrorProtocolVersionMismatch) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_parse_error.json" - : "updatecheck_reply_parse_error.xml"))); + test_file("updatecheck_reply_parse_error.json"))); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); @@ -1426,8 +1192,7 @@ TEST_P(UpdateCheckerTest, ParseErrorAppStatusErrorUnknownApplication) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file(use_JSON_ ? "updatecheck_reply_unknownapp.json" - : "updatecheck_reply_unknownapp.xml"))); + test_file("updatecheck_reply_unknownapp.json"))); update_checker_ = UpdateChecker::Create(config_, metadata_.get());
diff --git a/components/update_client/update_client_unittest.cc b/components/update_client/update_client_unittest.cc index 20e2dd6..6b40ab0 100644 --- a/components/update_client/update_client_unittest.cc +++ b/components/update_client/update_client_unittest.cc
@@ -31,7 +31,7 @@ #include "components/update_client/network.h" #include "components/update_client/persisted_data.h" #include "components/update_client/ping_manager.h" -#include "components/update_client/protocol_parser.h" +#include "components/update_client/protocol_handler.h" #include "components/update_client/test_configurator.h" #include "components/update_client/test_installer.h" #include "components/update_client/update_checker.h" @@ -3453,19 +3453,21 @@ EXPECT_EQ(4u, ids_to_check.size()); const std::string update_response = - R"(<?xml version="1.0" encoding="UTF-8"?>)" - R"(<response protocol="3.1">)" - R"(<app appid="jebgalgnebhfojomionfpkfelancnnkf")" - R"( status="error-unknownApplication"/>)" - R"(<app appid="abagagagagagagagagagagagagagagag")" - R"( status="restricted"/>)" - R"(<app appid="ihfokbkgjpifnbbojhneepfflplebdkc")" - R"( status="error-invalidAppId"/>)" - R"(<app appid="gjpmebpgbhcamgdgjcmnjfhggjpgcimm")" - R"( status="error-foobarApp"/>)" - R"(</response>)"; + ")]}'" + R"({"response": {)" + R"( "protocol": "3.1",)" + R"( "app": [)" + R"({"appid": "jebgalgnebhfojomionfpkfelancnnkf",)" + R"( "status": "error-unknownApplication"},)" + R"({"appid": "abagagagagagagagagagagagagagagag",)" + R"( "status": "restricted"},)" + R"({"appid": "ihfokbkgjpifnbbojhneepfflplebdkc",)" + R"( "status": "error-invalidAppId"},)" + R"({"appid": "gjpmebpgbhcamgdgjcmnjfhggjpgcimm",)" + R"( "status": "error-foobarApp"})" + R"(]}})"; - const auto parser = ProtocolParser::Create(); + const auto parser = ProtocolHandlerFactoryJSON().CreateParser(); EXPECT_TRUE(parser->Parse(update_response)); base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc index 499504c..abdfcd6f 100644 --- a/components/viz/service/display/renderer_pixeltest.cc +++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -847,6 +847,35 @@ child_resource_provider, child_context_provider); } +// Create two quads of specified colors on half-pixel boundaries. +void CreateTestAxisAlignedQuads(const gfx::Rect& rect, + SkColor front_color, + SkColor back_color, + bool needs_blending, + bool force_aa_off, + RenderPass* pass) { + gfx::Transform front_quad_to_target_transform; + front_quad_to_target_transform.Translate(50, 50); + front_quad_to_target_transform.Scale(0.5f + 1.0f / (rect.width() * 2.0f), + 0.5f + 1.0f / (rect.height() * 2.0f)); + SharedQuadState* front_shared_state = CreateTestSharedQuadState( + front_quad_to_target_transform, rect, pass, gfx::RRectF()); + + auto* front = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + front->SetAll(front_shared_state, rect, rect, needs_blending, front_color, + force_aa_off); + + gfx::Transform back_quad_to_target_transform; + back_quad_to_target_transform.Translate(25.5f, 25.5f); + back_quad_to_target_transform.Scale(0.5f, 0.5f); + SharedQuadState* back_shared_state = CreateTestSharedQuadState( + back_quad_to_target_transform, rect, pass, gfx::RRectF()); + + auto* back = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); + back->SetAll(back_shared_state, rect, rect, needs_blending, back_color, + force_aa_off); +} + using RendererTypes = ::testing::Types<GLRenderer, SoftwareRenderer, @@ -3146,8 +3175,8 @@ } // This test tests that anti-aliasing works for axis aligned quads. -// Anti-aliasing is only supported in the gl renderer. -TYPED_TEST(GLOnlyRendererPixelTest, AxisAligned) { +// Anti-aliasing is only supported in the gl and skia renderers. +TYPED_TEST(GLCapableRendererPixelTest, AxisAligned) { gfx::Rect rect(this->device_viewport_size_); int id = 1; @@ -3155,24 +3184,8 @@ std::unique_ptr<RenderPass> pass = CreateTestRenderPass(id, rect, transform_to_root); - gfx::Transform red_quad_to_target_transform; - red_quad_to_target_transform.Translate(50, 50); - red_quad_to_target_transform.Scale(0.5f + 1.0f / (rect.width() * 2.0f), - 0.5f + 1.0f / (rect.height() * 2.0f)); - SharedQuadState* red_shared_state = CreateTestSharedQuadState( - red_quad_to_target_transform, rect, pass.get(), gfx::RRectF()); - - auto* red = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); - red->SetNew(red_shared_state, rect, rect, SK_ColorRED, false); - - gfx::Transform yellow_quad_to_target_transform; - yellow_quad_to_target_transform.Translate(25.5f, 25.5f); - yellow_quad_to_target_transform.Scale(0.5f, 0.5f); - SharedQuadState* yellow_shared_state = CreateTestSharedQuadState( - yellow_quad_to_target_transform, rect, pass.get(), gfx::RRectF()); - - auto* yellow = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); - yellow->SetNew(yellow_shared_state, rect, rect, SK_ColorYELLOW, false); + CreateTestAxisAlignedQuads(rect, SK_ColorRED, SK_ColorYELLOW, false, false, + pass.get()); gfx::Transform blue_quad_to_target_transform; SharedQuadState* blue_shared_state = CreateTestSharedQuadState( @@ -3352,6 +3365,29 @@ cc::ExactPixelComparator(false))); } +// This test tests that forcing anti-aliasing off works as expected while +// blending is still enabled. +// Anti-aliasing is only supported in the gl and skia renderers. +TYPED_TEST(GLCapableRendererPixelTest, BlendingWithoutAntiAliasing) { + gfx::Rect rect(this->device_viewport_size_); + + int id = 1; + gfx::Transform transform_to_root; + std::unique_ptr<RenderPass> pass = + CreateTestRenderPass(id, rect, transform_to_root); + + CreateTestAxisAlignedQuads(rect, 0x800000FF, 0x8000FF00, true, true, + pass.get()); + + RenderPassList pass_list; + pass_list.push_back(std::move(pass)); + + EXPECT_TRUE(this->RunPixelTest( + &pass_list, + base::FilePath(FILE_PATH_LITERAL("translucent_quads_no_aa.png")), + cc::ExactPixelComparator(false))); +} + // Trilinear filtering is only supported in the gl renderer. TYPED_TEST(GLCapableRendererPixelTest, TrilinearFiltering) { gfx::Rect viewport_rect(this->device_viewport_size_); @@ -4558,25 +4594,8 @@ std::unique_ptr<RenderPass> pass = CreateTestRenderPass(id, rect, transform_to_root); - gfx::Transform dark_gray_quad_to_target_transform; - dark_gray_quad_to_target_transform.Translate(50, 50); - dark_gray_quad_to_target_transform.Scale( - 0.5f + 1.0f / (rect.width() * 2.0f), - 0.5f + 1.0f / (rect.height() * 2.0f)); - SharedQuadState* dark_gray_shared_state = CreateTestSharedQuadState( - dark_gray_quad_to_target_transform, rect, pass.get(), gfx::RRectF()); - - auto* dark_gray = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); - dark_gray->SetNew(dark_gray_shared_state, rect, rect, 0x10444444, false); - - gfx::Transform light_gray_quad_to_target_transform; - light_gray_quad_to_target_transform.Translate(25.5f, 25.5f); - light_gray_quad_to_target_transform.Scale(0.5f, 0.5f); - SharedQuadState* light_gray_shared_state = CreateTestSharedQuadState( - light_gray_quad_to_target_transform, rect, pass.get(), gfx::RRectF()); - - auto* light_gray = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); - light_gray->SetNew(light_gray_shared_state, rect, rect, 0x10CCCCCC, false); + CreateTestAxisAlignedQuads(rect, 0x10444444, 0x10CCCCCC, true, false, + pass.get()); gfx::Transform bg_quad_to_target_transform; SharedQuadState* bg_shared_state = CreateTestSharedQuadState( @@ -4616,25 +4635,8 @@ std::unique_ptr<RenderPass> pass = CreateTestRenderPass(id, rect, transform_to_root); - gfx::Transform dark_gray_quad_to_target_transform; - dark_gray_quad_to_target_transform.Translate(50, 50); - dark_gray_quad_to_target_transform.Scale( - 0.5f + 1.0f / (rect.width() * 2.0f), - 0.5f + 1.0f / (rect.height() * 2.0f)); - SharedQuadState* dark_gray_shared_state = CreateTestSharedQuadState( - dark_gray_quad_to_target_transform, rect, pass.get(), gfx::RRectF()); - - auto* dark_gray = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); - dark_gray->SetNew(dark_gray_shared_state, rect, rect, 0x10444444, false); - - gfx::Transform light_gray_quad_to_target_transform; - light_gray_quad_to_target_transform.Translate(25.5f, 25.5f); - light_gray_quad_to_target_transform.Scale(0.5f, 0.5f); - SharedQuadState* light_gray_shared_state = CreateTestSharedQuadState( - light_gray_quad_to_target_transform, rect, pass.get(), gfx::RRectF()); - - auto* light_gray = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); - light_gray->SetNew(light_gray_shared_state, rect, rect, 0x10CCCCCC, false); + CreateTestAxisAlignedQuads(rect, 0x10444444, 0x10CCCCCC, true, false, + pass.get()); gfx::Transform bg_quad_to_target_transform; SharedQuadState* bg_shared_state = CreateTestSharedQuadState(
diff --git a/components/viz/service/main/viz_compositor_thread_runner.cc b/components/viz/service/main/viz_compositor_thread_runner.cc index 076546e..bc76bac 100644 --- a/components/viz/service/main/viz_compositor_thread_runner.cc +++ b/components/viz/service/main/viz_compositor_thread_runner.cc
@@ -49,10 +49,7 @@ auto thread = std::make_unique<base::Thread>(kThreadName); base::Thread::Options thread_options; -#if defined(OS_WIN) - // Windows needs a UI message loop for child HWND. - thread_options.message_loop_type = base::MessageLoop::TYPE_UI; -#elif defined(USE_OZONE) +#if defined(USE_OZONE) // We may need a non-default message loop type for the platform surface. thread_options.message_loop_type = ui::OzonePlatform::GetInstance()->GetMessageLoopTypeForGpu();
diff --git a/components/viz/test/data/translucent_quads_no_aa.png b/components/viz/test/data/translucent_quads_no_aa.png new file mode 100644 index 0000000..9df8374 --- /dev/null +++ b/components/viz/test/data/translucent_quads_no_aa.png Binary files differ
diff --git a/content/browser/accessibility/site_per_process_accessibility_browsertest.cc b/content/browser/accessibility/site_per_process_accessibility_browsertest.cc index 241e5fa6..be09e2e 100644 --- a/content/browser/accessibility/site_per_process_accessibility_browsertest.cc +++ b/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
@@ -136,8 +136,9 @@ EXPECT_EQ(ax_child_frame_root->PlatformGetParent(), ax_iframe); } +// TODO(aboxhall): Flaky test, discuss with dmazzoni IN_PROC_BROWSER_TEST_F(MAYBE_SitePerProcessAccessibilityBrowserTest, - TwoCrossSiteNavigations) { + DISABLED_TwoCrossSiteNavigations) { // Enable full accessibility for all current and future WebContents. BrowserAccessibilityState::GetInstance()->EnableAccessibility();
diff --git a/content/browser/download/mhtml_generation_browsertest.cc b/content/browser/download/mhtml_generation_browsertest.cc index 38ea178..97edcac6 100644 --- a/content/browser/download/mhtml_generation_browsertest.cc +++ b/content/browser/download/mhtml_generation_browsertest.cc
@@ -96,29 +96,54 @@ // static int FindTrackingDelegate::global_request_id = 0; -} // namespace +const char kTestData[] = + "Sample Text to write on a generated MHTML " + "file for tests to validate whether the implementation is able to access " + "and write to the file."; -// This Mock injects our overwritten interface, running the callback -// SerializeAsMHTMLResponse and immediately disconnecting the message pipe. -class MockMhtmlFileWriter : public mojom::MhtmlFileWriter { +class MockWriterBase : public mojom::MhtmlFileWriter { public: - explicit MockMhtmlFileWriter() : binding_(this) {} - - ~MockMhtmlFileWriter() override {} + MockWriterBase() : binding_(this) {} + ~MockWriterBase() override {} void BindRequest(mojo::ScopedInterfaceEndpointHandle handle) { binding_.Bind(mojom::MhtmlFileWriterAssociatedRequest(std::move(handle))); } + protected: + void SendResponse(SerializeAsMHTMLCallback callback) { + std::vector<std::string> dummy_digests; + base::TimeDelta dummy_time_delta = base::TimeDelta::FromMilliseconds(100); + std::move(callback).Run(mojom::MhtmlSaveStatus::kSuccess, dummy_digests, + dummy_time_delta); + } + void WriteDataToDestinationFile(base::File& destination_file) { - const char kTestData[] = - "Sample Text to write on generated MHTML " - "file to verify it has been written to."; base::ScopedAllowBlockingForTesting allow_blocking; destination_file.WriteAtCurrentPos(kTestData, strlen(kTestData)); destination_file.Close(); } + void WriteDataToProducerPipe( + mojo::ScopedDataPipeProducerHandle producer_pipe) { + base::ScopedAllowBlockingForTesting allow_blocking; + uint32_t size = strlen(kTestData); + producer_pipe->WriteData(kTestData, &size, MOJO_WRITE_DATA_FLAG_NONE); + producer_pipe.reset(); + } + + mojo::AssociatedBinding<mojom::MhtmlFileWriter> binding_; + + private: + DISALLOW_COPY_AND_ASSIGN(MockWriterBase); +}; + +// This Mock injects our overwritten interface, running the callback +// SerializeAsMHTMLResponse and immediately disconnecting the message pipe. +class RespondAndDisconnectMockWriter : public MockWriterBase { + public: + RespondAndDisconnectMockWriter() {} + void SerializeAsMHTML(mojom::SerializeAsMHTMLParamsPtr params, SerializeAsMHTMLCallback callback) override { // Upon using the overridden mock interface implementation, this will be @@ -174,36 +199,73 @@ // then accepts the error notification and invokes the connection error // handler, guaranteeing its execution before (3). - // Write a valid MHTML file to destination_file, since we are not - // actively running a serialization pipeline in the mock implementation. - WriteDataToDestinationFile(params->destination_file); + bool compute_contents_hash = params->output_handle->is_producer_handle(); - std::vector<std::string> dummy_digests; - base::TimeDelta dummy_time_delta = base::TimeDelta::Max(); - std::move(callback).Run(mojom::MhtmlSaveStatus::kSuccess, dummy_digests, - dummy_time_delta); + // Write a valid MHTML file to its respective handle, since we are not + // actively running a serialization pipeline in the mock implementation. + if (compute_contents_hash) { + WriteDataToProducerPipe( + std::move(params->output_handle->get_producer_handle())); + } else { + WriteDataToDestinationFile(params->output_handle->get_file_handle()); + } + + SendResponse(std::move(callback)); // Close the message pipe connection to invoke the connection error // callback. The connection error handler from here will finalize // the Job and attempt to call MHTMLGenerationManager::Job::CloseFile // a second time. If this situation is handled correctly, the // browser file should be invalidated and idempotent. - binding_.Unbind(); + if (!compute_contents_hash) { + binding_.Unbind(); + return; + } + + // In the case we are using a data pipe to stream serialized MHTML data, + // we must ensure the write complete notification arrives before the + // connection error notification, otherwise the Browser will report + // an MhtmlSaveStatus != kSuccess. We can guarantee this by potentially + // running tasks after each watcher invocation to send notifications that + // it has been completed. We need at least two tasks to guarantee this, + // as there can be at most two watcher invocations to write a block of + // data smaller than the data pipe buffer to file. + download::GetDownloadTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&RespondAndDisconnectMockWriter::TaskX, + base::Unretained(this))); } - private: - mojo::AssociatedBinding<mojom::MhtmlFileWriter> binding_; + void TaskX() { + download::GetDownloadTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&RespondAndDisconnectMockWriter::TaskY, + base::Unretained(this))); + } - DISALLOW_COPY_AND_ASSIGN(MockMhtmlFileWriter); + void TaskY() { + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::UI}, + base::BindOnce(&RespondAndDisconnectMockWriter::TaskZ, + base::Unretained(this))); + } + + void TaskZ() { binding_.Unbind(); } + + private: + DISALLOW_COPY_AND_ASSIGN(RespondAndDisconnectMockWriter); }; -class MHTMLGenerationTest : public ContentBrowserTest { +} // namespace + +class MHTMLGenerationTest : public ContentBrowserTest, + public testing::WithParamInterface<bool> { public: MHTMLGenerationTest() : has_mhtml_callback_run_(false), file_size_(0), well_formedness_check_(true) {} + enum TaskOrder { WriteThenRespond, RespondThenWrite }; + protected: void SetUpOnMainThread() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); @@ -211,19 +273,34 @@ ContentBrowserTest::SetUpOnMainThread(); } - void GenerateMHTML(const base::FilePath& path, const GURL& url) { - GenerateMHTML(MHTMLGenerationParams(path), url); + void OverrideInterface(MockWriterBase* mock_writer) { + blink::AssociatedInterfaceProvider* remote_interfaces = + shell() + ->web_contents() + ->GetMainFrame() + ->GetRemoteAssociatedInterfaces(); + remote_interfaces->OverrideBinderForTesting( + mojom::MhtmlFileWriter::Name_, + base::BindRepeating(&MockWriterBase::BindRequest, + base::Unretained(mock_writer))); } - void GenerateMHTML(const MHTMLGenerationParams& params, const GURL& url) { + void GenerateMHTML(base::FilePath& path, const GURL& url) { + MHTMLGenerationParams params(path); + GenerateMHTML(params, url); + } + + void GenerateMHTML(MHTMLGenerationParams& params, const GURL& url) { NavigateToURL(shell(), url); GenerateMHTMLForCurrentPage(params); } - void GenerateMHTMLForCurrentPage(const MHTMLGenerationParams& params) { + void GenerateMHTMLForCurrentPage(MHTMLGenerationParams& params) { base::RunLoop run_loop; histogram_tester_.reset(new base::HistogramTester()); + params.compute_contents_hash = GetParam(); + shell()->web_contents()->GenerateMHTML( params, base::BindOnce(&MHTMLGenerationTest::MHTMLGenerated, base::Unretained(this), run_loop.QuitClosure())); @@ -254,6 +331,8 @@ shell()->web_contents()->SetDelegate(old_delegate); } + void TwoStepSyncTestFor(const TaskOrder order); + int64_t ReadFileSizeFromDisk(base::FilePath path) { base::ScopedAllowBlockingForTesting allow_blocking; int64_t file_size; @@ -263,7 +342,7 @@ void TestOriginalVsSavedPage( const GURL& url, - const MHTMLGenerationParams params, + MHTMLGenerationParams params, int expected_number_of_frames, const std::vector<std::string>& expected_substrings, const std::vector<std::string>& forbidden_substrings_in_saved_page, @@ -352,7 +431,7 @@ // Note that the actual content of the file is not tested, the purpose of this // test is to ensure we were successful in creating the MHTML data from the // renderer. -IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTML) { +IN_PROC_BROWSER_TEST_P(MHTMLGenerationTest, GenerateMHTML) { base::FilePath path(temp_dir_.GetPath()); path = path.Append(FILE_PATH_LITERAL("test.mht")); @@ -377,22 +456,18 @@ } // Regression test for the crash/race from https://crbug.com/612098. -IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLAndCloseConnection) { - MockMhtmlFileWriter mock_writer; +IN_PROC_BROWSER_TEST_P(MHTMLGenerationTest, GenerateMHTMLAndCloseConnection) { + RespondAndDisconnectMockWriter mock_writer; NavigateToURL(shell(), embedded_test_server()->GetURL("/simple_page.html")); base::FilePath path(temp_dir_.GetPath()); path = path.Append(FILE_PATH_LITERAL("test.mht")); - blink::AssociatedInterfaceProvider* remote_interfaces = - shell()->web_contents()->GetMainFrame()->GetRemoteAssociatedInterfaces(); - remote_interfaces->OverrideBinderForTesting( - mojom::MhtmlFileWriter::Name_, - base::BindRepeating(&MockMhtmlFileWriter::BindRequest, - base::Unretained(&mock_writer))); - + OverrideInterface(&mock_writer); DisableWellformednessCheck(); - GenerateMHTMLForCurrentPage(MHTMLGenerationParams(path)); + + MHTMLGenerationParams params(path); + GenerateMHTMLForCurrentPage(params); // Verify the file has some contents written to it. EXPECT_GT(ReadFileSizeFromDisk(path), 100); @@ -406,7 +481,7 @@ #else #define MAYBE_InvalidPath InvalidPath #endif -IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, MAYBE_InvalidPath) { +IN_PROC_BROWSER_TEST_P(MHTMLGenerationTest, MAYBE_InvalidPath) { base::FilePath path(FILE_PATH_LITERAL("/invalid/file/path")); GenerateMHTML(path, embedded_test_server()->GetURL( @@ -423,7 +498,7 @@ // Tests that MHTML generated using the default 'quoted-printable' encoding does // not contain the 'binary' Content-Transfer-Encoding header, and generates // base64 encoding for the image part. -IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateNonBinaryMHTMLWithImage) { +IN_PROC_BROWSER_TEST_P(MHTMLGenerationTest, GenerateNonBinaryMHTMLWithImage) { base::FilePath path(temp_dir_.GetPath()); path = path.Append(FILE_PATH_LITERAL("test_binary.mht")); @@ -447,7 +522,7 @@ // Tests that MHTML generated using the binary encoding contains the 'binary' // Content-Transfer-Encoding header, and does not contain any base64 encoded // parts. -IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateBinaryMHTMLWithImage) { +IN_PROC_BROWSER_TEST_P(MHTMLGenerationTest, GenerateBinaryMHTMLWithImage) { base::FilePath path(temp_dir_.GetPath()); path = path.Append(FILE_PATH_LITERAL("test_binary.mht")); @@ -471,7 +546,7 @@ } } -IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLIgnoreNoStore) { +IN_PROC_BROWSER_TEST_P(MHTMLGenerationTest, GenerateMHTMLIgnoreNoStore) { base::FilePath path(temp_dir_.GetPath()); path = path.Append(FILE_PATH_LITERAL("test.mht")); @@ -502,7 +577,7 @@ ViewedMHTMLContainsNoStoreContent #endif -IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, +IN_PROC_BROWSER_TEST_P(MHTMLGenerationTest, MAYBE_ViewedMHTMLContainsNoStoreContent) { // Generate MHTML. base::FilePath path(temp_dir_.GetPath()); @@ -545,7 +620,7 @@ }; // Test for crbug.com/538766. -IN_PROC_BROWSER_TEST_F(MHTMLGenerationSitePerProcessTest, GenerateMHTML) { +IN_PROC_BROWSER_TEST_P(MHTMLGenerationSitePerProcessTest, GenerateMHTML) { base::FilePath path(temp_dir_.GetPath()); path = path.Append(FILE_PATH_LITERAL("test.mht")); @@ -571,7 +646,7 @@ EXPECT_THAT(mhtml, ContainsRegex("Content-Location:.*/title1.html")); } -IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, RemovePopupOverlay) { +IN_PROC_BROWSER_TEST_P(MHTMLGenerationTest, RemovePopupOverlay) { base::FilePath path(temp_dir_.GetPath()); path = path.Append(FILE_PATH_LITERAL("test.mht")); @@ -593,7 +668,7 @@ EXPECT_THAT(mhtml, Not(HasSubstr("class=3D\"modal"))); } -IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLWithExtraData) { +IN_PROC_BROWSER_TEST_P(MHTMLGenerationTest, GenerateMHTMLWithExtraData) { const char kFakeSignalData1[] = "FakeSignalData1"; const char kFakeSignalData2[] = "OtherMockDataForSignals"; const char kFakeContentType[] = "text/plain"; @@ -602,7 +677,6 @@ base::FilePath path(temp_dir_.GetPath()); path = path.Append(FILE_PATH_LITERAL("test.mht")); GURL url(embedded_test_server()->GetURL("/page_with_image.html")); - MHTMLGenerationParams params(path); // Place the extra data we need into the web contents user data. std::string content_type(kFakeContentType); @@ -619,7 +693,7 @@ extra_parts->AddExtraMHTMLPart(content_type, content_location, extra_headers, kFakeSignalData2); EXPECT_EQ(extra_parts->size(), 2); - GenerateMHTML(params, url); + GenerateMHTML(path, url); EXPECT_TRUE(has_mhtml_callback_run()); @@ -634,4 +708,147 @@ EXPECT_THAT(mhtml, HasSubstr(kFakeSignalData2)); } +IN_PROC_BROWSER_TEST_P(MHTMLGenerationTest, GenerateMHTMLWithMultipleFrames) { + base::FilePath path(temp_dir_.GetPath()); + path = path.Append(FILE_PATH_LITERAL("test.mht")); + + const std::string kContentURLs[] = { + "Content-Location:.*/page_with_image.html", + "Content-Location:.*/page_with_popup.html", + "Content-Location:.*/page_with_frameset.html", + "Content-Location:.*/page_with_allowfullscreen_frame.html", + "Content-Location:.*/page_with_iframe_and_link.html"}; + + MHTMLGenerationParams params(path); + TestOriginalVsSavedPage( + embedded_test_server()->GetURL("/page_with_multiple_iframes.html"), + params, 11 /* expected number of frames */, std::vector<std::string>(), + std::vector<std::string>()); + + // Test whether generation was successful. + EXPECT_GT(file_size(), 0); // Verify the size reported by the callback. + EXPECT_GT(ReadFileSizeFromDisk(path), 100); // Verify the actual file size. + + std::string mhtml; + { + base::ScopedAllowBlockingForTesting allow_blocking; + ASSERT_TRUE(base::ReadFileToString(path, &mhtml)); + } + + // Expect all frames in the .html are included in the generated file. + for (const auto& regex : kContentURLs) + EXPECT_THAT(mhtml, ContainsRegex(regex)); +} + +// Tests for the synchronization logic that waits for both the Mojo +// response and the data pipe closure to consider a frame serialization done. +// This is only relevant when a Mojo data pipe is being used (hash computation +// case) and is skipped if writing directly to file. +namespace { +class OrderedTaskMockWriter : public MockWriterBase { + public: + explicit OrderedTaskMockWriter(MHTMLGenerationTest::TaskOrder order) + : order_(order) {} + + void SerializeAsMHTML(mojom::SerializeAsMHTMLParamsPtr params, + SerializeAsMHTMLCallback callback) override { + DCHECK(params->output_handle->is_producer_handle()); + DCHECK(params->output_handle->get_producer_handle()->is_valid()); + + switch (order_) { + case MHTMLGenerationTest::TaskOrder::RespondThenWrite: + delayed_callback_ = base::BindOnce( + &OrderedTaskMockWriter::WriteDataToProducerPipe, + base::Unretained(this), + std::move(params->output_handle->get_producer_handle())); + SendResponse(std::move(callback)); + PostClosure(); + break; + case MHTMLGenerationTest::TaskOrder::WriteThenRespond: + delayed_callback_ = + base::BindOnce(&OrderedTaskMockWriter::SendResponse, + base::Unretained(this), std::move(callback)); + WriteDataToProducerPipe( + std::move(params->output_handle->get_producer_handle())); + // For this case, we must post to the download sequence first to + // ensure we run the closure after the write operation completes. + download::GetDownloadTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&OrderedTaskMockWriter::PostClosure, + base::Unretained(this))); + break; + } + } + + // Posts the quit closure to the UI thread to unblock the serialization Job + // after receiving the first task complete notification. + void PostClosure() { + base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, + std::move(first_run_loop_closure_)); + } + + base::OnceClosure first_run_loop_closure_; + base::OnceClosure delayed_callback_; + + private: + MHTMLGenerationTest::TaskOrder order_; + + DISALLOW_COPY_AND_ASSIGN(OrderedTaskMockWriter); +}; +} // namespace + +void MHTMLGenerationTest::TwoStepSyncTestFor( + const MHTMLGenerationTest::TaskOrder order) { + OrderedTaskMockWriter mock_writer(order); + + base::FilePath path(temp_dir_.GetPath()); + path = path.Append(FILE_PATH_LITERAL("test.mht")); + + MHTMLGenerationParams params(path); + + OverrideInterface(&mock_writer); + + base::RunLoop first_run_loop; + base::RunLoop second_run_loop; + + params.compute_contents_hash = true; + mock_writer.first_run_loop_closure_ = first_run_loop.QuitWhenIdleClosure(); + + shell()->web_contents()->GenerateMHTML( + params, + base::BindOnce(&MHTMLGenerationTest::MHTMLGenerated, + base::Unretained(this), second_run_loop.QuitClosure())); + + // Run serialization pipeline until stalled. + first_run_loop.Run(); + ASSERT_FALSE(has_mhtml_callback_run()) + << "MHTML generation complete but should be waiting on operation."; + + // Run stalled task and block until MHTML generation completes. + DCHECK(mock_writer.delayed_callback_); + std::move(mock_writer.delayed_callback_).Run(); + second_run_loop.Run(); + + ASSERT_TRUE(has_mhtml_callback_run()) + << "MHTML generation has not been complete despite unblocking the Job."; + + // Verify the file has some contents written to it. + EXPECT_GT(ReadFileSizeFromDisk(path), 100); + // Verify the reported file size matches the file written to disk. + EXPECT_EQ(ReadFileSizeFromDisk(path), file_size_); +} + +// These tests do not depend on the parameter declared by the +// MHTMLGenerationTest test suite, so we only want to run them once. +IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLButDelayWrite) { + TwoStepSyncTestFor(TaskOrder::RespondThenWrite); +} + +IN_PROC_BROWSER_TEST_F(MHTMLGenerationTest, GenerateMHTMLButDelayResponse) { + TwoStepSyncTestFor(TaskOrder::WriteThenRespond); +} + +INSTANTIATE_TEST_SUITE_P(MHTMLGenerationTest, + MHTMLGenerationTest, + ::testing::Bool()); + } // namespace content
diff --git a/content/browser/download/mhtml_generation_manager.cc b/content/browser/download/mhtml_generation_manager.cc index b529f36..9e524c5 100644 --- a/content/browser/download/mhtml_generation_manager.cc +++ b/content/browser/download/mhtml_generation_manager.cc
@@ -37,6 +37,10 @@ #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" namespace { +// Callback to notify the UI thread that writing to the MHTML file is complete. +using MHTMLWriteCompleteCallback = + base::RepeatingCallback<void(content::mojom::MhtmlSaveStatus)>; + const char kContentLocation[] = "Content-Location: "; const char kContentType[] = "Content-Type: "; int kInvalidFileSize = -1; @@ -46,6 +50,26 @@ content::mojom::MhtmlSaveStatus save_status; int64_t file_size; }; + +base::File CreateMHTMLFile(const base::FilePath& file_path) { + DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence()); + + // SECURITY NOTE: A file descriptor to the file created below will be passed + // to multiple renderer processes which (in out-of-process iframes mode) can + // act on behalf of separate web principals. Therefore it is important to + // only allow writing to the file and forbid reading from the file (as this + // would allow reading content generated by other renderers / other web + // principals). + uint32_t file_flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE; + + base::File browser_file(file_path, file_flags); + if (!browser_file.IsValid()) { + DLOG(ERROR) << "Failed to create file to save MHTML at: " + << file_path.value(); + } + return browser_file; +} + } // namespace namespace content { @@ -74,16 +98,20 @@ GenerateMHTMLCallback callback); ~Job(); - // Writes the MHTML footer to the file and closes it. + // Writes the MHTML footer to the file and closes it. It also receives the + // SimpleWatcher instance used to watch the data pipe for safe destruction on + // the IO thread. // // Note: The same |boundary| marker must be used for all "boundaries" -- in // the header, parts and footer -- that belong to the same MHTML document (see // also rfc1341, section 7.2.1, "boundary" description). - static CloseFileResult FinalizeAndCloseFileOnFileThread( + static CloseFileResult FinalizeOnFileThread( mojom::MhtmlSaveStatus save_status, const std::string& boundary, base::File file, - const std::vector<MHTMLExtraDataPart>& extra_data_parts); + const std::vector<MHTMLExtraDataPart>& extra_data_parts, + std::unique_ptr<mojo::SimpleWatcher> watcher); + void AddFrame(RenderFrameHost* render_frame_host); // If we have any extra MHTML parts to write out, write them into the file @@ -94,7 +122,7 @@ base::File& file, const std::vector<MHTMLExtraDataPart>& extra_data_parts); - // Writes the footer into the MHTML file. Returns false for faiulre. + // Writes the footer into the MHTML file. Returns false for failure. static bool WriteFooter(const std::string& boundary, base::File& file); // Called on the UI thread when the file that should hold the MHTML data has @@ -105,6 +133,28 @@ // or an error occurred while creating a new file. void OnFinished(const CloseFileResult& close_file_result); + // Starts watching a handle on the file thread. Instantiates a new instance + // of |watcher_| upon call. + void BeginWatchingHandle(MHTMLWriteCompleteCallback callback); + + // Writes data from the consumer handle to the new MHTML file. Only done + // with on the fly hash computation. + // Bound to the data pipe watcher and called upon notification of write + // completion to producer pipe sent to the Renderer. + // TODO(https://crbug.com/915966): Eventually simplify this implementation + // with a DataPipeDrainer once error signalling is implemented there. + void WriteMHTMLToDisk(MHTMLWriteCompleteCallback callback, + MojoResult result, + const mojo::HandleSignalsState& state); + + // Destroys |watcher_| instance and notifies UI thread of write completion. + void OnWriteComplete(MHTMLWriteCompleteCallback callback, + mojom::MhtmlSaveStatus save_status); + + // Notifies Job of frame write completion and sends request to next render + // frame if the response was blocked by the write operation. + void DoneWritingToDisk(mojom::MhtmlSaveStatus save_status); + // Called when the message pipe to the renderer is disconnected. void OnConnectionError(); @@ -116,13 +166,15 @@ base::TimeDelta renderer_main_thread_time); // Records newly serialized resource digests into - // |digests_of_already_serialized_uris_|, and continues sending serialization - // requests to the next frame if there are more frames to be serialized. - // Returns MhtmlSaveStatus::kSuccess or a specific error status. - mojom::MhtmlSaveStatus RecordDigestsAndContinue( + // |digests_of_already_serialized_uris_|. + void RecordDigests( const std::vector<std::string>& digests_of_uris_of_serialized_resources); - // Packs up the current status of the MHTML file saving into a Mojo + // Continues sending serialization requests to the next frame if ready and + // there are more frames to be serialized. + void MaybeSendToNextRenderFrame(mojom::MhtmlSaveStatus save_status); + + // Packs up the current status of the MHTML file save operation into a Mojo // struct to send to the renderer process. mojom::SerializeAsMHTMLParamsPtr CreateMojoParams(); @@ -131,11 +183,11 @@ // specific error status. mojom::MhtmlSaveStatus SendToNextRenderFrame(); - // Indicates if more calls to SendToNextRenderFrame are needed. - // This check is necessary to prevent a race condition between the - // Renderer and Browser where the Job is deleted before the response - // is received. - bool IsDone() const; + // Indicates if the writing operation on the IO thread is complete, and + // we have received a response from the Renderer. + // This check is necessary to provide synchronization between file writing + // operations and MHTML serialization. + bool CurrentFrameDone() const; // Called on the UI thread when a job has been finished. void Finalize(mojom::MhtmlSaveStatus save_status); @@ -145,6 +197,8 @@ // negative in case of errors). void CloseFile(mojom::MhtmlSaveStatus save_status); + // Marks the Job as completed, preventing any further notifications from the + // Renderer. This prevents the race/crash from https://crbug.com/612098. void MarkAsFinished(); void ReportRendererMainThreadTime(base::TimeDelta renderer_main_thread_time); @@ -193,9 +247,20 @@ // Any extra data parts that should be emitted into the output MHTML. std::vector<MHTMLExtraDataPart> extra_data_parts_; - // MHTML File Writer pointer to keep the variable alive. + // MHTMLFileWriter instance for the frame being currently serialized. mojom::MhtmlFileWriterAssociatedPtr writer_; + // Watcher to detect new data written to |mhtml_data_consumer_|. + // This is instantiated and destroyed in the download sequence for each frame. + std::unique_ptr<mojo::SimpleWatcher> watcher_; + + // Consumer handle for data pipe streaming. + mojo::ScopedDataPipeConsumerHandle mhtml_data_consumer_; + + // Indicates whether there is currently data being streamed from the Renderer. + // Not used when the renderer is writing directly to file. + bool waiting_on_data_streaming_; + base::WeakPtrFactory<Job> weak_factory_; DISALLOW_COPY_AND_ASSIGN(Job); @@ -211,6 +276,7 @@ salt_(base::GenerateGUID()), callback_(std::move(callback)), is_finished_(false), + waiting_on_data_streaming_(false), weak_factory_(this) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -236,12 +302,13 @@ base::PostTaskAndReplyWithResult( download::GetDownloadTaskRunner().get(), FROM_HERE, - base::BindOnce(&CreateFile, params.file_path), + base::BindOnce(&CreateMHTMLFile, params.file_path), base::BindOnce(&Job::OnFileAvailable, weak_factory_.GetWeakPtr())); } MHTMLGenerationManager::Job::~Job() { DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(!watcher_); } mojom::SerializeAsMHTMLParamsPtr @@ -253,9 +320,6 @@ mojo_params->mhtml_popup_overlay_removal = params_.remove_popup_overlay; mojo_params->mhtml_problem_detection = params_.use_page_problem_detectors; - // File::Duplicate() creates a reference to this file for use in the Renderer. - mojo_params->destination_file = browser_file_.Duplicate(); - // Tell the renderer to skip (= deduplicate) already covered MHTML parts. mojo_params->salt = salt_; mojo_params->digests_of_uris_to_skip.assign( @@ -279,28 +343,138 @@ // Bind Mojo interface to the RenderFrame rfh->GetRemoteAssociatedInterfaces()->GetInterface(&writer_); - auto callback = base::BindOnce(&Job::SerializeAsMHTMLResponse, - weak_factory_.GetWeakPtr()); // Safe, as |writer_| is owned by this Job instance. auto error_callback = base::BindOnce(&Job::OnConnectionError, base::Unretained(this)); writer_.set_connection_error_handler(std::move(error_callback)); - // Send a Mojo request asking to serialize the frame. + mojom::SerializeAsMHTMLParamsPtr params(CreateMojoParams()); + + // Initialize method of file writing depending on |compute_contents_hash| + // flag. + params->output_handle = mojom::MhtmlOutputHandle::New(); + if (params_.compute_contents_hash) { + // Create and set up the data pipe. + mojo::ScopedDataPipeProducerHandle producer; + if (mojo::CreateDataPipe(nullptr, &producer, &mhtml_data_consumer_) != + MOJO_RESULT_OK) { + DLOG(ERROR) << "Failed to create Mojo Data Pipe."; + return mojom::MhtmlSaveStatus::kStreamingError; + } + MHTMLWriteCompleteCallback write_complete_callback = base::BindRepeating( + &Job::DoneWritingToDisk, weak_factory_.GetWeakPtr()); + download::GetDownloadTaskRunner().get()->PostTask( + FROM_HERE, + base::BindOnce(&Job::BeginWatchingHandle, base::Unretained(this), + std::move(write_complete_callback))); + waiting_on_data_streaming_ = true; + params->output_handle->set_producer_handle(std::move(producer)); + } else { + // File::Duplicate() creates a reference to this file for use in the + // Renderer. + params->output_handle->set_file_handle(browser_file_.Duplicate()); + } + + // Send a Mojo request to Renderer to serialize its frame. DCHECK_EQ(FrameTreeNode::kFrameTreeNodeInvalidId, frame_tree_node_id_of_busy_frame_); frame_tree_node_id_of_busy_frame_ = frame_tree_node_id; - writer_->SerializeAsMHTML(CreateMojoParams(), std::move(callback)); + + auto response_callback = base::BindOnce(&Job::SerializeAsMHTMLResponse, + weak_factory_.GetWeakPtr()); + writer_->SerializeAsMHTML(std::move(params), std::move(response_callback)); TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("page-serialization", "WaitingOnRenderer", this, "frame tree node id", - frame_tree_node_id); + frame_tree_node_id_of_busy_frame_); DCHECK(wait_on_renderer_start_time_.is_null()); wait_on_renderer_start_time_ = base::TimeTicks::Now(); return mojom::MhtmlSaveStatus::kSuccess; } +void MHTMLGenerationManager::Job::BeginWatchingHandle( + MHTMLWriteCompleteCallback callback) { + DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence()); + + DCHECK(!watcher_); + watcher_ = std::make_unique<mojo::SimpleWatcher>( + FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC, + download::GetDownloadTaskRunner()); + + // base::Unretained is safe, as |this| owns |mhtml_data_consumer_|, which + // is responsible for invoking |watcher_| callbacks. + if (watcher_->Watch( + mhtml_data_consumer_.get(), + MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, + MOJO_WATCH_CONDITION_SATISFIED, + base::BindRepeating(&Job::WriteMHTMLToDisk, base::Unretained(this), + callback)) != MOJO_RESULT_OK) { + DLOG(ERROR) << "Failed to strap watcher to consumer handle."; + OnWriteComplete(callback, mojom::MhtmlSaveStatus::kStreamingError); + } +} + +void MHTMLGenerationManager::Job::WriteMHTMLToDisk( + MHTMLWriteCompleteCallback callback, + MojoResult result, + const mojo::HandleSignalsState& state) { + DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence()); + DCHECK_NE(result, MOJO_RESULT_FAILED_PRECONDITION); + + // Begin consumer data pipe handle read and file write loop. + char buffer[1024]; + while (result == MOJO_RESULT_OK && state.readable()) { + uint32_t num_bytes = sizeof(buffer); + result = mhtml_data_consumer_->ReadData(&buffer, &num_bytes, + MOJO_READ_DATA_FLAG_NONE); + + if (result == MOJO_RESULT_OK && + browser_file_.WriteAtCurrentPos(buffer, num_bytes) < 0) { + DLOG(ERROR) << "Error writing to file handle."; + OnWriteComplete(std::move(callback), + mojom::MhtmlSaveStatus::kFileWritingError); + return; + } + } + + if (result != MOJO_RESULT_OK && result != MOJO_RESULT_FAILED_PRECONDITION && + result != MOJO_RESULT_SHOULD_WAIT) { + DLOG(ERROR) << "Error streaming MHTML data to the Browser."; + OnWriteComplete(std::move(callback), + mojom::MhtmlSaveStatus::kStreamingError); + return; + } + + // Only notify successful write completion if peer handle is closed without + // any errors. + if (state.peer_closed()) + OnWriteComplete(std::move(callback), mojom::MhtmlSaveStatus::kSuccess); +} + +void MHTMLGenerationManager::Job::OnWriteComplete( + MHTMLWriteCompleteCallback callback, + mojom::MhtmlSaveStatus save_status) { + DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence()); + + watcher_.reset(); + base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, + base::BindOnce(std::move(callback), save_status)); +} + +void MHTMLGenerationManager::Job::DoneWritingToDisk( + mojom::MhtmlSaveStatus save_status) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + // If the Job has prematurely finalized and marked as finished, make this + // response no-op. + if (is_finished_) + return; + + waiting_on_data_streaming_ = false; + MaybeSendToNextRenderFrame(save_status); +} + void MHTMLGenerationManager::Job::OnConnectionError() { DCHECK_CURRENTLY_ON(BrowserThread::UI); // If message pipe end closes, then it is an unexpected crash. @@ -353,6 +527,11 @@ is_finished_ = true; writer_.reset(); + // Additionally, |watcher_| may also invoke DoneWritingToDisk() from + // the download sequence, potentially calling this twice. We cannot disable + // |watcher_| notifications similar to |writer_|, since it exists in + // the download sequence, so we handle the case in DoneWritingToDisk(). + TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("page-serialization", "JobFinished", this); @@ -404,24 +583,18 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!mhtml_boundary_marker_.empty()); - if (!browser_file_.IsValid()) { - // Only update the status if that won't hide an earlier error. - if (save_status == mojom::MhtmlSaveStatus::kSuccess) - save_status = mojom::MhtmlSaveStatus::kFileWritingError; - OnFinished(CloseFileResult(save_status, -1)); - return; - } + // Only update the status if that won't hide an earlier error. + if (!browser_file_.IsValid() && + save_status == mojom::MhtmlSaveStatus::kSuccess) + save_status = mojom::MhtmlSaveStatus::kFileWritingError; // If no previous error occurred the boundary should be sent. base::PostTaskAndReplyWithResult( download::GetDownloadTaskRunner().get(), FROM_HERE, - base::BindOnce( - &MHTMLGenerationManager::Job::FinalizeAndCloseFileOnFileThread, - save_status, - (save_status == mojom::MhtmlSaveStatus::kSuccess - ? mhtml_boundary_marker_ - : std::string()), - std::move(browser_file_), std::move(extra_data_parts_)), + base::BindOnce(&MHTMLGenerationManager::Job::FinalizeOnFileThread, + save_status, mhtml_boundary_marker_, + std::move(browser_file_), std::move(extra_data_parts_), + std::move(watcher_)), base::BindOnce(&Job::OnFinished, weak_factory_.GetWeakPtr())); } @@ -437,25 +610,14 @@ frame_tree_node_id_of_busy_frame_ = FrameTreeNode::kFrameTreeNodeInvalidId; - // If the renderer succeeded, update the status. - if (save_status == mojom::MhtmlSaveStatus::kSuccess) { - save_status = - RecordDigestsAndContinue(digests_of_uris_of_serialized_resources); - } + // If the renderer succeeded, update the resource digests. + if (save_status == mojom::MhtmlSaveStatus::kSuccess) + RecordDigests(digests_of_uris_of_serialized_resources); - // If there was a failure (either from the renderer or from the job) then - // terminate the job and return. - if (save_status != mojom::MhtmlSaveStatus::kSuccess) { - Finalize(save_status); - return; - } - - // Otherwise report completion if the job is done. - if (IsDone()) - Finalize(mojom::MhtmlSaveStatus::kSuccess); + MaybeSendToNextRenderFrame(save_status); } -mojom::MhtmlSaveStatus MHTMLGenerationManager::Job::RecordDigestsAndContinue( +void MHTMLGenerationManager::Job::RecordDigests( const std::vector<std::string>& digests_of_uris_of_serialized_resources) { DCHECK(!wait_on_renderer_start_time_.is_null()); base::TimeDelta renderer_wait_time = @@ -477,20 +639,35 @@ digests_of_already_serialized_uris_.insert( digests_of_uris_of_serialized_resources.begin(), digests_of_uris_of_serialized_resources.end()); - - // Report success if all frames have been processed. - if (pending_frame_tree_node_ids_.empty()) - return mojom::MhtmlSaveStatus::kSuccess; - - return SendToNextRenderFrame(); } -bool MHTMLGenerationManager::Job::IsDone() const { +void MHTMLGenerationManager::Job::MaybeSendToNextRenderFrame( + mojom::MhtmlSaveStatus save_status) { + // If current operation is successful and there are more frames to process, + // let save status depend on the result of sending the next request. + if (save_status == mojom::MhtmlSaveStatus::kSuccess && + !pending_frame_tree_node_ids_.empty() && CurrentFrameDone()) { + save_status = SendToNextRenderFrame(); + } + + // If there was a failure (either from the renderer or from the job) then + // terminate the job and return. + if (save_status != mojom::MhtmlSaveStatus::kSuccess) { + Finalize(save_status); + return; + } + + // Otherwise report completion if there are no more frames to process + // and Job is done processing the current frame. + if (pending_frame_tree_node_ids_.empty() && CurrentFrameDone()) + Finalize(mojom::MhtmlSaveStatus::kSuccess); +} + +bool MHTMLGenerationManager::Job::CurrentFrameDone() const { bool waiting_for_response_from_renderer = frame_tree_node_id_of_busy_frame_ != FrameTreeNode::kFrameTreeNodeInvalidId; - bool no_more_requests_to_send = pending_frame_tree_node_ids_.empty(); - return !waiting_for_response_from_renderer && no_more_requests_to_send; + return !waiting_for_response_from_renderer && !waiting_on_data_streaming_; } void MHTMLGenerationManager::Job::Finalize(mojom::MhtmlSaveStatus save_status) { @@ -511,13 +688,16 @@ } // static -CloseFileResult MHTMLGenerationManager::Job::FinalizeAndCloseFileOnFileThread( +CloseFileResult MHTMLGenerationManager::Job::FinalizeOnFileThread( mojom::MhtmlSaveStatus save_status, const std::string& boundary, base::File file, - const std::vector<MHTMLExtraDataPart>& extra_data_parts) { + const std::vector<MHTMLExtraDataPart>& extra_data_parts, + std::unique_ptr<mojo::SimpleWatcher> watcher) { DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence()); + watcher.reset(); + // If no previous error occurred the boundary should have been provided. if (save_status == mojom::MhtmlSaveStatus::kSuccess) { TRACE_EVENT0("page-serialization", @@ -620,24 +800,4 @@ Job::StartNewJob(web_contents, params, std::move(callback)); } -// static -base::File MHTMLGenerationManager::CreateFile(const base::FilePath& file_path) { - DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence()); - - // SECURITY NOTE: A file descriptor to the file created below will be passed - // to multiple renderer processes which (in out-of-process iframes mode) can - // act on behalf of separate web principals. Therefore it is important to - // only allow writing to the file and forbid reading from the file (as this - // would allow reading content generated by other renderers / other web - // principals). - uint32_t file_flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE; - - base::File browser_file(file_path, file_flags); - if (!browser_file.IsValid()) { - DLOG(ERROR) << "Failed to create file to save MHTML at: " - << file_path.value(); - } - return browser_file; -} - } // namespace content
diff --git a/content/browser/download/mhtml_generation_manager.h b/content/browser/download/mhtml_generation_manager.h index 9cfa5c1..fc79bd2 100644 --- a/content/browser/download/mhtml_generation_manager.h +++ b/content/browser/download/mhtml_generation_manager.h
@@ -10,16 +10,11 @@ #include <set> #include <string> -#include "base/files/file.h" #include "base/macros.h" #include "base/memory/singleton.h" #include "base/process/process.h" #include "content/public/common/mhtml_generation_params.h" -namespace base { -class FilePath; -} - namespace content { class WebContents; @@ -45,9 +40,6 @@ const MHTMLGenerationParams& params, GenerateMHTMLCallback callback); - // Called on the file thread to create a new file for MHTML serialization. - static base::File CreateFile(const base::FilePath& file_path); - private: friend struct base::DefaultSingletonTraits<MHTMLGenerationManager>; class Job;
diff --git a/content/browser/frame_host/navigation_controller_android.cc b/content/browser/frame_host/navigation_controller_android.cc index 1baf7aa..519b640 100644 --- a/content/browser/frame_host/navigation_controller_android.cc +++ b/content/browser/frame_host/navigation_controller_android.cc
@@ -9,6 +9,7 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/callback.h" +#include "base/containers/flat_map.h" #include "base/strings/string16.h" #include "content/browser/frame_host/navigation_controller_impl.h" #include "content/browser/frame_host/navigation_entry_impl.h" @@ -30,6 +31,8 @@ namespace { +const char kMapDataKey[] = "map_data_key"; + // static static base::android::ScopedJavaLocalRef<jobject> JNI_NavigationControllerImpl_CreateJavaNavigationEntry( @@ -71,6 +74,36 @@ index)); } +class MapData : public base::SupportsUserData::Data { + public: + MapData() = default; + ~MapData() override = default; + + static MapData* Get(content::NavigationEntry* entry) { + MapData* map_data = static_cast<MapData*>(entry->GetUserData(kMapDataKey)); + if (map_data) + return map_data; + auto map_data_ptr = std::make_unique<MapData>(); + map_data = map_data_ptr.get(); + entry->SetUserData(kMapDataKey, std::move(map_data_ptr)); + return map_data; + } + + base::flat_map<std::string, base::string16>& map() { return map_; } + + // base::SupportsUserData::Data: + std::unique_ptr<Data> Clone() override { + std::unique_ptr<MapData> clone = std::make_unique<MapData>(); + clone->map_ = map_; + return clone; + } + + private: + base::flat_map<std::string, base::string16> map_; + + DISALLOW_COPY_AND_ASSIGN(MapData); +}; + } // namespace namespace content { @@ -389,9 +422,11 @@ return ScopedJavaLocalRef<jstring>(); std::string key = base::android::ConvertJavaStringToUTF8(env, jkey); - base::string16 value; - navigation_controller_->GetEntryAtIndex(index)->GetExtraData(key, &value); - return ConvertUTF16ToJavaString(env, value); + MapData* map_data = + MapData::Get(navigation_controller_->GetEntryAtIndex(index)); + auto iter = map_data->map().find(key); + return ConvertUTF16ToJavaString( + env, iter == map_data->map().end() ? base::string16() : iter->second); } void NavigationControllerAndroid::SetEntryExtraData( @@ -405,7 +440,9 @@ std::string key = base::android::ConvertJavaStringToUTF8(env, jkey); base::string16 value = base::android::ConvertJavaStringToUTF16(env, jvalue); - navigation_controller_->GetEntryAtIndex(index)->SetExtraData(key, value); + MapData* map_data = + MapData::Get(navigation_controller_->GetEntryAtIndex(index)); + map_data->map()[key] = value; } jboolean NavigationControllerAndroid::IsEntryMarkedToBeSkipped(
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc index ef34341f..85482344 100644 --- a/content/browser/frame_host/navigation_entry_impl.cc +++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -604,24 +604,6 @@ return can_load_local_resources_; } -void NavigationEntryImpl::SetExtraData(const std::string& key, - const base::string16& data) { - extra_data_[key] = data; -} - -bool NavigationEntryImpl::GetExtraData(const std::string& key, - base::string16* data) { - auto iter = extra_data_.find(key); - if (iter == extra_data_.end()) - return false; - *data = iter->second; - return true; -} - -void NavigationEntryImpl::ClearExtraData(const std::string& key) { - extra_data_.erase(key); -} - std::unique_ptr<NavigationEntryImpl> NavigationEntryImpl::Clone() const { return NavigationEntryImpl::CloneAndReplace(nullptr, false, nullptr, nullptr); } @@ -669,7 +651,7 @@ // ResetForCommit: frame_tree_node_id_ copy->has_user_gesture_ = has_user_gesture_; // ResetForCommit: reload_type_ - copy->extra_data_ = extra_data_; + copy->CloneDataFrom(*this); copy->replaced_entry_data_ = replaced_entry_data_; copy->should_skip_on_back_forward_ui_ = should_skip_on_back_forward_ui_;
diff --git a/content/browser/frame_host/navigation_entry_impl.h b/content/browser/frame_host/navigation_entry_impl.h index 105f3ac..f7f3b75f 100644 --- a/content/browser/frame_host/navigation_entry_impl.h +++ b/content/browser/frame_host/navigation_entry_impl.h
@@ -139,10 +139,6 @@ base::Time GetTimestamp() override; void SetCanLoadLocalResources(bool allow) override; bool GetCanLoadLocalResources() override; - void SetExtraData(const std::string& key, - const base::string16& data) override; - bool GetExtraData(const std::string& key, base::string16* data) override; - void ClearExtraData(const std::string& key) override; void SetHttpStatusCode(int http_status_code) override; int GetHttpStatusCode() override; void SetRedirectChain(const std::vector<GURL>& redirects) override; @@ -532,11 +528,6 @@ // Determine if the navigation was started within a context menu. bool started_from_context_menu_; - // Used to store extra data to support browser features. This member is not - // persisted, unless specific data is taken out/put back in at save/restore - // time (see TabNavigation for an example of this). - std::map<std::string, base::string16> extra_data_; - // Set to true if the navigation controller gets notified about a SSL error // for a pending navigation. Defaults to false. bool ssl_error_;
diff --git a/content/browser/frame_host/navigation_entry_impl_unittest.cc b/content/browser/frame_host/navigation_entry_impl_unittest.cc index 3d7e8f9..4bd938e 100644 --- a/content/browser/frame_host/navigation_entry_impl_unittest.cc +++ b/content/browser/frame_host/navigation_entry_impl_unittest.cc
@@ -317,27 +317,6 @@ EXPECT_EQ(now, entry1_->GetTimestamp()); } -// Test extra data stored in the navigation entry. -TEST_F(NavigationEntryTest, NavigationEntryExtraData) { - base::string16 test_data = ASCIIToUTF16("my search terms"); - base::string16 output; - entry1_->SetExtraData("search_terms", test_data); - - EXPECT_FALSE(entry1_->GetExtraData("non_existent_key", &output)); - EXPECT_EQ(ASCIIToUTF16(""), output); - EXPECT_TRUE(entry1_->GetExtraData("search_terms", &output)); - EXPECT_EQ(test_data, output); - // Data is cleared. - entry1_->ClearExtraData("search_terms"); - // Content in |output| is not modified if data is not present at the key. - EXPECT_FALSE(entry1_->GetExtraData("search_terms", &output)); - EXPECT_EQ(test_data, output); - // Using an empty string shows that the data is not present in the map. - base::string16 output2; - EXPECT_FALSE(entry1_->GetExtraData("search_terms", &output2)); - EXPECT_EQ(ASCIIToUTF16(""), output2); -} - #if defined(OS_ANDROID) // Test that content URIs correctly show the file display name as the title. TEST_F(NavigationEntryTest, NavigationEntryContentUri) {
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc index 64bb4b9..8ffc145 100644 --- a/content/browser/renderer_host/input/input_router_impl.cc +++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -55,12 +55,22 @@ } } -ui::WebScopedInputEvent ScaleEvent(const WebInputEvent& event, double scale) { +std::unique_ptr<InputEvent> ScaleEvent(const WebInputEvent& event, + double scale, + const ui::LatencyInfo latency_info) { std::unique_ptr<blink::WebInputEvent> event_in_viewport = ui::ScaleWebInputEvent(event, scale); - if (event_in_viewport) - return ui::WebScopedInputEvent(event_in_viewport.release()); - return ui::WebInputEventTraits::Clone(event); + if (event_in_viewport) { + ui::LatencyInfo scaled_latency_info(latency_info); + scaled_latency_info.set_scroll_update_delta( + latency_info.scroll_update_delta() * scale); + return std::make_unique<InputEvent>( + ui::WebScopedInputEvent(event_in_viewport.release()), + scaled_latency_info); + } + + return std::make_unique<InputEvent>(ui::WebInputEventTraits::Clone(event), + latency_info); } } // namespace @@ -520,8 +530,8 @@ return; } - std::unique_ptr<InputEvent> event = std::make_unique<InputEvent>( - ScaleEvent(input_event, device_scale_factor_), latency_info); + std::unique_ptr<InputEvent> event = + ScaleEvent(input_event, device_scale_factor_, latency_info); if (WebInputEventTraits::ShouldBlockEventStream(input_event)) { TRACE_EVENT_INSTANT0("input", "InputEventSentBlocking", TRACE_EVENT_SCOPE_THREAD);
diff --git a/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc b/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc index 33662f3c..fd04742 100644 --- a/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc +++ b/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
@@ -1204,115 +1204,4 @@ EXPECT_TRUE(HistogramSizeEq("Event.Latency.EndToEnd.TouchpadPinch", 1)); } -TEST_F(RenderWidgetHostLatencyTrackerTest, TestScrollUpdateAverageLag) { - // Simulate a simple situation that events at every 10ms and start at t=15ms, - // frame swaps at every 10ms too and start at t=20ms. - base::TimeTicks event_time = - base::TimeTicks() + base::TimeDelta::FromMilliseconds(5); - base::TimeTicks frame_time = - base::TimeTicks() + base::TimeDelta::FromMilliseconds(10); - { - // ScrollBegin - SyntheticWebTouchEvent touch; - touch.PressPoint(0, 0); - ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH); - - touch_latency.set_scroll_update_delta(10); - event_time += base::TimeDelta::FromMilliseconds(10); // 15ms - touch_latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, - event_time, 1); - touch_latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, event_time, - 1); - - frame_time += base::TimeDelta::FromMilliseconds(10); // 20ms - AddFakeComponentsWithTimeStamp(*tracker(), &touch_latency, frame_time); - AddRenderingScheduledComponent(&touch_latency, - false /* rendering_on_main */, frame_time); - tracker()->OnInputEvent(touch, &touch_latency); - tracker()->OnInputEventAck(touch, &touch_latency, - INPUT_EVENT_ACK_STATE_NOT_CONSUMED); - viz_tracker()->OnGpuSwapBuffersCompleted(touch_latency); - } - // Send 101 ScrollUpdate events to verify that there is 1 AverageLag record - // per 1 second. - const int kUpdates = 101; - for (int i = 0; i < kUpdates; i++) { - // ScrollUpdate - SyntheticWebTouchEvent touch; - touch.PressPoint(0, 0); - ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH); - - const int sign = (i < kUpdates / 2) ? 1 : -1; - touch_latency.set_scroll_update_delta(sign * 10); - event_time += base::TimeDelta::FromMilliseconds(10); - touch_latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, event_time, - 1); - touch_latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, event_time, - 1); - - frame_time += base::TimeDelta::FromMilliseconds(10); - AddFakeComponentsWithTimeStamp(*tracker(), &touch_latency, frame_time); - AddRenderingScheduledComponent(&touch_latency, false /*rendering_on_main*/, - frame_time); - tracker()->OnInputEvent(touch, &touch_latency); - tracker()->OnInputEventAck(touch, &touch_latency, - INPUT_EVENT_ACK_STATE_NOT_CONSUMED); - viz_tracker()->OnGpuSwapBuffersCompleted(touch_latency); - } - // ScrollBegin report_time is at 20ms, so the next ScrollUpdate report_time is - // at 1020ms. The last event_time that finish this report should be later than - // 1020ms. - EXPECT_EQ(event_time, - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1025)); - EXPECT_EQ(frame_time, - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1030)); - - // ScrollBegin AverageLag are the area between the event original component - // (time=15ms, delta=10px) to the frame swap time (time=20ms, expect finger - // position at delta=15px). The AverageLag scaled to 1 second is - // (5ms*10px+5ms*5px/2)/5ms = 12.5px. - EXPECT_THAT(histogram_tester().GetAllSamples( - "Event.Latency.ScrollBegin.Touch.AverageLag"), - ElementsAre(Bucket(12, 1))); - // This ScrollUpdate AverageLag are calculated as the finger uniformly scroll - // 10px each frame. For each frame, the Lag on the last frame start is 5px, - // and Lag on this frame swap is 15px, so the AverageLag in 1 second is 10px. - EXPECT_THAT(histogram_tester().GetAllSamples( - "Event.Latency.ScrollUpdate.Touch.AverageLag"), - ElementsAre(Bucket(10, 1))); - ResetHistograms(); - - { - // Send another ScrollBegin to end the unfinished ScrollUpdate report. - SyntheticWebTouchEvent touch; - touch.PressPoint(0, 0); - ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH); - - event_time += base::TimeDelta::FromMilliseconds(10); - touch_latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, - event_time, 1); - touch_latency.AddLatencyNumberWithTimestamp( - ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, event_time, - 1); - - frame_time += base::TimeDelta::FromMilliseconds(10); - AddFakeComponentsWithTimeStamp(*tracker(), &touch_latency, frame_time); - AddRenderingScheduledComponent(&touch_latency, - false /* rendering_on_main */, frame_time); - tracker()->OnInputEvent(touch, &touch_latency); - tracker()->OnInputEventAck(touch, &touch_latency, - INPUT_EVENT_ACK_STATE_NOT_CONSUMED); - viz_tracker()->OnGpuSwapBuffersCompleted(touch_latency); - } - // The last frame's lag is 8.75px and truncated to 8. - EXPECT_THAT(histogram_tester().GetAllSamples( - "Event.Latency.ScrollUpdate.Touch.AverageLag"), - ElementsAre(Bucket(8, 1))); -} - } // namespace content
diff --git a/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc b/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc index 69eb47a..38c4daf 100644 --- a/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc +++ b/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
@@ -110,25 +110,29 @@ return std::unique_ptr<ppapi::host::ResourceHost>(new PepperFileRefHost( host_, instance, resource, file_system, internal_path)); } - case PpapiHostMsg_TCPSocket_Create::ID: { - ppapi::TCPSocketVersion version; - if (!ppapi::UnpackMessage<PpapiHostMsg_TCPSocket_Create>(message, - &version) || - version == ppapi::TCP_SOCKET_VERSION_PRIVATE) { - return std::unique_ptr<ppapi::host::ResourceHost>(); - } + } - return CreateNewTCPSocket(instance, resource, version); - } - case PpapiHostMsg_UDPSocket_Create::ID: { - if (CanCreateSocket()) { + // Socket interfaces. + if (GetPermissions().HasPermission(ppapi::PERMISSION_SOCKET)) { + switch (message.type()) { + case PpapiHostMsg_TCPSocket_Create::ID: { + ppapi::TCPSocketVersion version; + if (!ppapi::UnpackMessage<PpapiHostMsg_TCPSocket_Create>(message, + &version) || + version == ppapi::TCP_SOCKET_VERSION_PRIVATE) { + return nullptr; + } + if (!CanCreateSocket()) + return nullptr; + return CreateNewTCPSocket(instance, resource, version); + } + case PpapiHostMsg_UDPSocket_Create::ID: { + if (!CanCreateSocket()) + return nullptr; scoped_refptr<ppapi::host::ResourceMessageFilter> udp_socket( new PepperUDPSocketMessageFilter(host_, instance, false)); - return std::unique_ptr<ppapi::host::ResourceHost>( - new ppapi::host::MessageFilterHost(host_->GetPpapiHost(), instance, - resource, udp_socket)); - } else { - return std::unique_ptr<ppapi::host::ResourceHost>(); + return std::make_unique<ppapi::host::MessageFilterHost>( + host_->GetPpapiHost(), instance, resource, udp_socket); } } }
diff --git a/content/browser/resources/appcache/appcache_internals.css b/content/browser/resources/appcache/appcache_internals.css index 0844ed5..b2fe53f3 100644 --- a/content/browser/resources/appcache/appcache_internals.css +++ b/content/browser/resources/appcache/appcache_internals.css
@@ -68,9 +68,17 @@ .appcache-info-template-file-url { width: 200px; - height:25px; + height: 25px; } .appcache-info-template-file-url { color: rgb(60, 102, 221); } + +.appcache-details { + text-align: start; +} + +.appcache-details td { + width: 80px; +}
diff --git a/content/browser/resources/appcache/appcache_internals.html b/content/browser/resources/appcache/appcache_internals.html index 45ce6bb..7dfd489 100644 --- a/content/browser/resources/appcache/appcache_internals.html +++ b/content/browser/resources/appcache/appcache_internals.html
@@ -80,19 +80,31 @@ </div> </div> - <div id="appcache-info-template" jsselect="$this.items"> - <span> - <a href="#" class="appcache-info-template-file-url" - jscontent="fileUrl" jsvalues=".responseId:responseId"> - </a> - </span> - <span jscontent="totalSize"></span> - = - <span jscontent="responseSize"></span> (response) - + - <span jscontent="paddingSize"></span> (padding) - <span jscontent="properties"></span> - </div> + <table id="appcache-info-template"> + <thead> + <tr> + <th>File URL</th> + <th>Total Size</th> + <th>Response</th> + <th>Padding</th> + <th>Properties</th> + </tr> + </thead> + <tbody class="appcache-details" + jsvalues=".manifestURL:$manifestURL;.groupId:$groupId;"> + <tr jsselect="items"> + <td> + <a href="#" class="appcache-info-template-file-url" + jscontent="fileUrl" jsvalues=".responseId:responseId"> + </a> + </td> + <td jscontent="totalSize"></td> + <td jscontent="responseSize"></td> + <td jscontent="paddingSize"></td> + <td jscontent="properties"></td> + </tr> + </tbody> + </table> </div> <h1>Application Cache</h1> <div class="content">
diff --git a/content/common/download/mhtml_file_writer.mojom b/content/common/download/mhtml_file_writer.mojom index 619f02a..04c3b71 100644 --- a/content/common/download/mhtml_file_writer.mojom +++ b/content/common/download/mhtml_file_writer.mojom
@@ -33,13 +33,22 @@ // A render process needed for the serialization of one of the page's frame is // no more. Determined by the browser. - kRenderProcessExited + kRenderProcessExited, + + // There is a problem reading or writing serialized data to the Data Pipe. + // Determined by either browser or renderer. + kStreamingError +}; + +union MhtmlOutputHandle { + // Destination file handle. + mojo_base.mojom.File file_handle; + + // Data pipe producer handle for on-the-fly hashing. + handle<data_pipe_producer> producer_handle; }; struct SerializeAsMHTMLParams { - // Destination file handle. - mojo_base.mojom.File destination_file; - // MHTML boundary marker / MIME multipart boundary maker. The same // |mhtml_boundary_marker| should be used for serialization of each frame. string mhtml_boundary_marker; @@ -67,10 +76,13 @@ // Salt used for |digests_of_uris_to_skip|. string salt; + + // Destination handle to write MHTML data to. + MhtmlOutputHandle output_handle; }; // Serialize target frame and its resources into MHTML and write it into the -// provided destination file handle. Note that when serializing multiple +// provided output handle. Note that when serializing multiple // frames, one needs to serialize the *main* frame first (the main frame // needs to go first according to RFC2557 + the main frame will trigger // generation of the MHTML header).
diff --git a/content/public/browser/navigation_entry.h b/content/public/browser/navigation_entry.h index ea0573d..e3c6f60f 100644 --- a/content/public/browser/navigation_entry.h +++ b/content/public/browser/navigation_entry.h
@@ -13,6 +13,7 @@ #include "base/memory/ref_counted_memory.h" #include "base/optional.h" #include "base/strings/string16.h" +#include "base/supports_user_data.h" #include "base/time/time.h" #include "build/build_config.h" #include "content/common/content_export.h" @@ -34,9 +35,9 @@ // required to recreate a browsing state. This includes some opaque binary // state as provided by the WebContents as well as some clear text title and // URL which is used for our user interface. -class NavigationEntry { +class NavigationEntry : public base::SupportsUserData { public: - virtual ~NavigationEntry() {} + ~NavigationEntry() override {} CONTENT_EXPORT static std::unique_ptr<NavigationEntry> Create(); @@ -193,15 +194,6 @@ virtual void SetCanLoadLocalResources(bool allow) = 0; virtual bool GetCanLoadLocalResources() = 0; - // Set extra data on this NavigationEntry according to the specified |key|. - // This data is not persisted by default. - virtual void SetExtraData(const std::string& key, - const base::string16& data) = 0; - // If present, fills the |data| present at the specified |key|. - virtual bool GetExtraData(const std::string& key, base::string16* data) = 0; - // Removes the data at the specified |key|. - virtual void ClearExtraData(const std::string& key) = 0; - // The status code of the last known successful navigation. If // GetHttpStatusCode() returns 0 that means that either: //
diff --git a/content/public/common/mhtml_generation_params.h b/content/public/common/mhtml_generation_params.h index d1fe446..479109f 100644 --- a/content/public/common/mhtml_generation_params.h +++ b/content/public/common/mhtml_generation_params.h
@@ -28,9 +28,9 @@ // Run page problem detectors while generating MTHML if true. bool use_page_problem_detectors = false; - // Whether to use Mojo for the MHTML serialization pipeline. + // Whether to compute the hash of the contents while saving the MHTML file. // This is triggered by the feature flag kOnTheFlyMhtmlHashComputation. - bool use_mojo_for_mhtml_serialization = false; + bool compute_contents_hash = false; }; } // namespace content
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index b9ff933..09c06057 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -397,6 +397,8 @@ "media_stream_utils.cc", "menu_item_builder.cc", "menu_item_builder.h", + "mhtml_handle_writer.cc", + "mhtml_handle_writer.h", "mojo/blink_interface_provider_impl.cc", "mojo/blink_interface_provider_impl.h", "mojo/blink_interface_registry_impl.cc",
diff --git a/content/renderer/dom_automation_controller.cc b/content/renderer/dom_automation_controller.cc index 4e7f80bf36..bf231fc 100644 --- a/content/renderer/dom_automation_controller.cc +++ b/content/renderer/dom_automation_controller.cc
@@ -36,8 +36,10 @@ return; v8::Local<v8::Object> global = context->Global(); - global->Set(gin::StringToV8(isolate, "domAutomationController"), - controller.ToV8()); + global + ->Set(context, gin::StringToV8(isolate, "domAutomationController"), + controller.ToV8()) + .Check(); } DomAutomationController::DomAutomationController(RenderFrame* render_frame) @@ -72,8 +74,10 @@ return; v8::Local<v8::Object> global = context->Global(); - global->Set(gin::StringToV8(isolate, "domAutomationController"), - controller.ToV8()); + global + ->Set(context, gin::StringToV8(isolate, "domAutomationController"), + controller.ToV8()) + .Check(); } bool DomAutomationController::SendMsg(const gin::Arguments& args) {
diff --git a/content/renderer/gpu_benchmarking_extension.cc b/content/renderer/gpu_benchmarking_extension.cc index 232c323c..b16d0b13 100644 --- a/content/renderer/gpu_benchmarking_extension.cc +++ b/content/renderer/gpu_benchmarking_extension.cc
@@ -544,7 +544,10 @@ return; v8::Local<v8::Object> chrome = GetOrCreateChromeObject(isolate, context); - chrome->Set(gin::StringToV8(isolate, "gpuBenchmarking"), controller.ToV8()); + chrome + ->Set(context, gin::StringToV8(isolate, "gpuBenchmarking"), + controller.ToV8()) + .Check(); } GpuBenchmarking::GpuBenchmarking(RenderFrameImpl* frame)
diff --git a/content/renderer/mhtml_handle_writer.cc b/content/renderer/mhtml_handle_writer.cc new file mode 100644 index 0000000..c6eb1c0 --- /dev/null +++ b/content/renderer/mhtml_handle_writer.cc
@@ -0,0 +1,176 @@ +// 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 "content/renderer/mhtml_handle_writer.h" + +#include "base/metrics/histogram_macros.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" +#include "content/common/download/mhtml_file_writer.mojom.h" +#include "content/public/renderer/render_thread.h" +#include "third_party/blink/public/platform/web_thread_safe_data.h" + +namespace content { + +MHTMLHandleWriter::MHTMLHandleWriter( + scoped_refptr<base::TaskRunner> main_thread_task_runner, + MHTMLWriteCompleteCallback callback) + : main_thread_task_runner_(std::move(main_thread_task_runner)), + callback_(std::move(callback)) {} + +MHTMLHandleWriter::~MHTMLHandleWriter() {} + +void MHTMLHandleWriter::WriteContents( + std::vector<blink::WebThreadSafeData> mhtml_contents) { + TRACE_EVENT_ASYNC_BEGIN0("page-serialization", + "Writing MHTML contents to handle", this); + DCHECK(mhtml_write_start_time_.is_null()); + mhtml_write_start_time_ = base::TimeTicks::Now(); + + WriteContentsImpl(std::move(mhtml_contents)); +} + +void MHTMLHandleWriter::Finish(mojom::MhtmlSaveStatus save_status) { + DCHECK(!RenderThread::IsMainThread()) + << "Should not run in the main renderer thread"; + + // Only record UMA if WriteContents has been called. + if (!mhtml_write_start_time_.is_null()) { + TRACE_EVENT_ASYNC_END0("page-serialization", + "WriteContentsImpl (MHTMLHandleWriter)", this); + base::TimeDelta mhtml_write_time = + base::TimeTicks::Now() - mhtml_write_start_time_; + UMA_HISTOGRAM_TIMES( + "PageSerialization.MhtmlGeneration.WriteToDiskTime.SingleFrame", + mhtml_write_time); + } + + Close(); + + main_thread_task_runner_->PostTask( + FROM_HERE, base::BindOnce(std::move(callback_), save_status)); + delete this; +} + +MHTMLFileHandleWriter::MHTMLFileHandleWriter( + scoped_refptr<base::TaskRunner> main_thread_task_runner, + MHTMLWriteCompleteCallback callback, + base::File file) + : MHTMLHandleWriter(std::move(main_thread_task_runner), + std::move(callback)), + file_(std::move(file)) {} + +MHTMLFileHandleWriter::~MHTMLFileHandleWriter() {} + +void MHTMLFileHandleWriter::WriteContentsImpl( + std::vector<blink::WebThreadSafeData> mhtml_contents) { + mojom::MhtmlSaveStatus save_status = mojom::MhtmlSaveStatus::kSuccess; + for (const blink::WebThreadSafeData& data : mhtml_contents) { + if (!data.IsEmpty() && + file_.WriteAtCurrentPos(data.Data(), data.size()) < 0) { + save_status = mojom::MhtmlSaveStatus::kFileWritingError; + break; + } + } + Finish(save_status); +} + +void MHTMLFileHandleWriter::Close() { + file_.Close(); +} + +MHTMLProducerHandleWriter::MHTMLProducerHandleWriter( + scoped_refptr<base::TaskRunner> main_thread_task_runner, + MHTMLWriteCompleteCallback callback, + mojo::ScopedDataPipeProducerHandle producer) + : MHTMLHandleWriter(std::move(main_thread_task_runner), + std::move(callback)), + producer_(std::move(producer)), + current_block_(0), + write_position_(0) {} + +void MHTMLProducerHandleWriter::WriteContentsImpl( + std::vector<blink::WebThreadSafeData> mhtml_contents) { + DCHECK(mhtml_contents_.empty()); + mhtml_contents_ = std::move(mhtml_contents); + + scoped_refptr<base::SequencedTaskRunner> task_runner = + base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}); + + task_runner->PostTask( + FROM_HERE, base::BindOnce(&MHTMLProducerHandleWriter::BeginWatchingHandle, + base::Unretained(this))); +} + +MHTMLProducerHandleWriter::~MHTMLProducerHandleWriter() {} + +void MHTMLProducerHandleWriter::Close() { + producer_.reset(); +} + +void MHTMLProducerHandleWriter::BeginWatchingHandle() { + // mojo::SimpleWatcher's constructor by default gets a reference ptr + // to the current SequencedTaskRunner if one is not specified, keeping + // the current SequencedTaskRunner's lifetime bound to |watcher_|. + watcher_ = std::make_unique<mojo::SimpleWatcher>( + FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC); + // Using base::Unretained is safe, as |this| owns |watcher_|. + watcher_->Watch( + producer_.get(), + MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, + MOJO_WATCH_CONDITION_SATISFIED, + base::BindRepeating(&MHTMLProducerHandleWriter::TryWritingContents, + base::Unretained(this))); +} + +// TODO(https://crbug.com/915966): This can be simplified with usage +// of BlockingCopyToString once error signalling is implemented and +// updated with usage of base::span instead of std::string. +void MHTMLProducerHandleWriter::TryWritingContents( + MojoResult result, + const mojo::HandleSignalsState& state) { + if (result != MOJO_RESULT_OK) { + DLOG(ERROR) + << "Error receiving notifications from producer handle watcher."; + Finish(mojom::MhtmlSaveStatus::kStreamingError); + return; + } + + while (true) { + const blink::WebThreadSafeData& data = mhtml_contents_.at(current_block_); + + // If there is no more data in this block, continue to next block or + // finish. + uint32_t num_bytes = data.size() - write_position_; + if (num_bytes == 0) { + write_position_ = 0; + if (++current_block_ >= mhtml_contents_.size()) { + Finish(mojom::MhtmlSaveStatus::kSuccess); + return; + } + continue; + } + + result = producer_->WriteData(data.Data() + write_position_, &num_bytes, + MOJO_WRITE_DATA_FLAG_NONE); + + // Break out of loop early if write was not successful to avoid + // incrementing the write position incorrectly. + if (result != MOJO_RESULT_OK) + break; + + // Reaching this indicates a successful write. + write_position_ += num_bytes; + DCHECK(write_position_ <= data.size()); + } + + if (result != MOJO_RESULT_SHOULD_WAIT) { + Finish(mojom::MhtmlSaveStatus::kStreamingError); + } + + // Buffer is full, return to automatically re-arm the watcher. +} + +} // namespace content \ No newline at end of file
diff --git a/content/renderer/mhtml_handle_writer.h b/content/renderer/mhtml_handle_writer.h new file mode 100644 index 0000000..6a44851 --- /dev/null +++ b/content/renderer/mhtml_handle_writer.h
@@ -0,0 +1,120 @@ +// 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 CONTENT_RENDERER_MHTML_HANDLE_WRITER_H_ +#define CONTENT_RENDERER_MHTML_HANDLE_WRITER_H_ + +#include <memory> +#include <vector> + +#include "base/files/file.h" +#include "content/common/download/mhtml_file_writer.mojom-forward.h" + +namespace blink { +class WebThreadSafeData; +} + +namespace content { + +// TODO(https://crbug.com/915966): This class needs unit tests. + +// Handle wrapper for MHTML serialization to abstract the handle which data +// is written to. This is instantiated on the heap and is responsible for +// destroying itself after completing its write operation. +// Should only live in blocking sequenced threads. +class MHTMLHandleWriter { + public: + using MHTMLWriteCompleteCallback = + base::OnceCallback<void(mojom::MhtmlSaveStatus)>; + + MHTMLHandleWriter(scoped_refptr<base::TaskRunner> main_thread_task_runner, + MHTMLWriteCompleteCallback callback); + virtual ~MHTMLHandleWriter(); + + void WriteContents(std::vector<blink::WebThreadSafeData> mhtml_contents); + + // Finalizes the writing operation, recording the UMA, closing the handle, + // and deleting itself. + void Finish(mojom::MhtmlSaveStatus save_status); + + protected: + virtual void WriteContentsImpl( + std::vector<blink::WebThreadSafeData> mhtml_contents) = 0; + + virtual void Close() = 0; + + private: + base::TimeTicks mhtml_write_start_time_; + + scoped_refptr<base::TaskRunner> main_thread_task_runner_; + MHTMLWriteCompleteCallback callback_; + + DISALLOW_COPY_AND_ASSIGN(MHTMLHandleWriter); +}; + +// Wraps a base::File target to write MHTML contents to. +// This implementation immediately finishes after writing all MHTML contents +// to the file handle. +class MHTMLFileHandleWriter : public MHTMLHandleWriter { + public: + MHTMLFileHandleWriter(scoped_refptr<base::TaskRunner> main_thread_task_runner, + MHTMLWriteCompleteCallback callback, + base::File file); + ~MHTMLFileHandleWriter() override; + + protected: + // Writes the serialized and encoded MHTML data from WebThreadSafeData + // instances directly to the file handle passed from the Browser. + void WriteContentsImpl( + std::vector<blink::WebThreadSafeData> mhtml_contents) override; + + void Close() override; + + private: + base::File file_; + + DISALLOW_COPY_AND_ASSIGN(MHTMLFileHandleWriter); +}; + +// Wraps a mojo::ScopedDataPipeProducerHandle target to write MHTML contents to. +// This implementation does not immediately finish and destroy itself due to +// the limited size of the data pipe buffer. We must ensure all data is +// written to the handle before finishing the write operation. +class MHTMLProducerHandleWriter : public MHTMLHandleWriter { + public: + MHTMLProducerHandleWriter( + scoped_refptr<base::TaskRunner> main_thread_task_runner, + MHTMLWriteCompleteCallback callback, + mojo::ScopedDataPipeProducerHandle producer); + ~MHTMLProducerHandleWriter() override; + + protected: + // Creates a new SequencedTaskRunner to dispatch |watcher_| invocations on. + void WriteContentsImpl( + std::vector<blink::WebThreadSafeData> mhtml_contents) override; + + void Close() override; + + private: + void BeginWatchingHandle(); + + // Writes the serialized and encoded MHTML data from WebThreadSafeData + // instances to producer while possible. + void TryWritingContents(MojoResult result, + const mojo::HandleSignalsState& state); + + mojo::ScopedDataPipeProducerHandle producer_; + + std::vector<blink::WebThreadSafeData> mhtml_contents_; + std::unique_ptr<mojo::SimpleWatcher> watcher_; + + size_t current_block_; + size_t write_position_; + + DISALLOW_COPY_AND_ASSIGN(MHTMLProducerHandleWriter); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MHTML_HANDLE_WRITER_H_ \ No newline at end of file
diff --git a/content/renderer/pepper/plugin_module.cc b/content/renderer/pepper/plugin_module.cc index b03756a..ebabd9b 100644 --- a/content/renderer/pepper/plugin_module.cc +++ b/content/renderer/pepper/plugin_module.cc
@@ -402,6 +402,7 @@ #include "ppapi/thunk/interfaces_ppb_private_pdf.h" #include "ppapi/thunk/interfaces_ppb_public_dev.h" #include "ppapi/thunk/interfaces_ppb_public_dev_channel.h" +#include "ppapi/thunk/interfaces_ppb_public_socket.h" #include "ppapi/thunk/interfaces_ppb_public_stable.h" #undef PROXIED_IFACE
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index c067241..6a61a8b 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -128,6 +128,7 @@ #include "content/renderer/media/stream/media_stream_device_observer.h" #include "content/renderer/media/stream/user_media_client_impl.h" #include "content/renderer/media/webrtc/rtc_peer_connection_handler.h" +#include "content/renderer/mhtml_handle_writer.h" #include "content/renderer/mojo/blink_interface_registry_impl.h" #include "content/renderer/navigation_client.h" #include "content/renderer/navigation_state.h" @@ -694,29 +695,52 @@ return request.HttpMethod().Utf8() == "POST"; } -// Writes to file the serialized and encoded MHTML data from WebThreadSafeData -// instances. -mojom::MhtmlSaveStatus WriteMHTMLToDisk( - std::vector<WebThreadSafeData> mhtml_contents, - base::File file) { - TRACE_EVENT0("page-serialization", "WriteMHTMLToDisk (RenderFrameImpl)"); - SCOPED_UMA_HISTOGRAM_TIMER( - "PageSerialization.MhtmlGeneration.WriteToDiskTime.SingleFrame"); - DCHECK(!RenderThread::IsMainThread()) - << "Should not run in the main renderer thread"; - mojom::MhtmlSaveStatus save_status = mojom::MhtmlSaveStatus::kSuccess; - for (const WebThreadSafeData& data : mhtml_contents) { - if (!data.IsEmpty() && - file.WriteAtCurrentPos(data.Data(), data.size()) < 0) { - save_status = mojom::MhtmlSaveStatus::kFileWritingError; - break; +// Delegate responsible for determining the handle writing implementation by +// instantiating an MHTMLHandleWriter on the heap respective to the passed in +// MHTMLSerializationParams. This transfers ownership of the handle to the +// new MHTMLHandleWriter. +class MHTMLHandleWriterDelegate { + public: + MHTMLHandleWriterDelegate( + mojom::SerializeAsMHTMLParams& params, + MHTMLHandleWriter::MHTMLWriteCompleteCallback callback, + scoped_refptr<base::TaskRunner> main_thread_task_runner) { + // Handle must be instantiated. + DCHECK(params.output_handle); + + if (params.output_handle->is_file_handle()) { + handle_ = new MHTMLFileHandleWriter( + std::move(main_thread_task_runner), std::move(callback), + std::move(params.output_handle->get_file_handle())); + } else { + handle_ = new MHTMLProducerHandleWriter( + std::move(main_thread_task_runner), std::move(callback), + std::move(params.output_handle->get_producer_handle())); } } - // Explicitly close |file| here to make sure to include any flush operations - // in the UMA metric. - file.Close(); - return save_status; -} + + void WriteContents(std::vector<WebThreadSafeData> mhtml_contents) { + // Using base::Unretained is safe, as calls to WriteContents() always + // deletes |handle| upon Finish(). + base::PostTaskWithTraits( + FROM_HERE, {base::MayBlock()}, + base::BindOnce(&MHTMLHandleWriter::WriteContents, + base::Unretained(handle_), std::move(mhtml_contents))); + } + + // Within the context of the delegate, only for premature write finish. + void Finish(mojom::MhtmlSaveStatus save_status) { + base::PostTaskWithTraits( + FROM_HERE, {base::MayBlock()}, + base::BindOnce(&MHTMLHandleWriter::Finish, base::Unretained(handle_), + save_status)); + } + + private: + MHTMLHandleWriter* handle_; + + DISALLOW_COPY_AND_ASSIGN(MHTMLHandleWriterDelegate); +}; FaviconURL::IconType ToFaviconType(blink::WebIconURL::Type type) { switch (type) { @@ -6594,7 +6618,7 @@ // Note: the MHTML footer is written by the browser process, after the last // frame is serialized by a renderer process. - // Note: we assume RenderFrameImpl::OnWriteMHTMLToDiskComplete and the rest of + // Note: we assume RenderFrameImpl::OnWriteMHTMLComplete and the rest of // this function will be fast enough to not need to be accounted for in this // metric. base::TimeDelta main_thread_use_time = base::TimeTicks::Now() - start_time; @@ -6602,30 +6626,27 @@ "PageSerialization.MhtmlGeneration.RendererMainThreadTime.SingleFrame", main_thread_use_time); + MHTMLHandleWriterDelegate handle_delegate( + *params, + base::BindOnce(&RenderFrameImpl::OnWriteMHTMLComplete, + weak_factory_.GetWeakPtr(), std::move(callback), + std::move(serialized_resources_uri_digests), + main_thread_use_time), + GetTaskRunner(blink::TaskType::kInternalDefault)); + if (save_status == mojom::MhtmlSaveStatus::kSuccess && has_some_data) { - base::PostTaskWithTraitsAndReplyWithResult( - FROM_HERE, {base::MayBlock()}, - base::BindOnce(&WriteMHTMLToDisk, std::move(mhtml_contents), - std::move(params->destination_file)), - base::BindOnce(&RenderFrameImpl::OnWriteMHTMLToDiskComplete, - weak_factory_.GetWeakPtr(), std::move(callback), - std::move(serialized_resources_uri_digests), - main_thread_use_time)); + handle_delegate.WriteContents(mhtml_contents); } else { - params->destination_file.Close(); - OnWriteMHTMLToDiskComplete(std::move(callback), - std::move(serialized_resources_uri_digests), - main_thread_use_time, save_status); + handle_delegate.Finish(save_status); } } -void RenderFrameImpl::OnWriteMHTMLToDiskComplete( +void RenderFrameImpl::OnWriteMHTMLComplete( SerializeAsMHTMLCallback callback, std::unordered_set<std::string> serialized_resources_uri_digests, base::TimeDelta main_thread_use_time, mojom::MhtmlSaveStatus save_status) { - TRACE_EVENT1("page-serialization", - "RenderFrameImpl::OnWriteMHTMLToDiskComplete", + TRACE_EVENT1("page-serialization", "RenderFrameImpl::OnWriteMHTMLComplete", "frame save status", save_status); DCHECK(RenderThread::IsMainThread()) << "Must run in the main renderer thread";
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index bf2ed251c..1f6e37c 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -1170,8 +1170,8 @@ #endif // Callback scheduled from SerializeAsMHTML for when writing serialized - // MHTML to file has been completed in the file thread. - void OnWriteMHTMLToDiskComplete( + // MHTML to the handle has been completed in the file thread. + void OnWriteMHTMLComplete( SerializeAsMHTMLCallback callback, std::unordered_set<std::string> serialized_resources_uri_digests, base::TimeDelta main_thread_use_time,
diff --git a/content/renderer/skia_benchmarking_extension.cc b/content/renderer/skia_benchmarking_extension.cc index 0ad993d7..e125a2d 100644 --- a/content/renderer/skia_benchmarking_extension.cc +++ b/content/renderer/skia_benchmarking_extension.cc
@@ -125,7 +125,10 @@ return; v8::Local<v8::Object> chrome = GetOrCreateChromeObject(isolate, context); - chrome->Set(gin::StringToV8(isolate, "skiaBenchmarking"), controller.ToV8()); + chrome + ->Set(context, gin::StringToV8(isolate, "skiaBenchmarking"), + controller.ToV8()) + .Check(); } // static @@ -277,21 +280,31 @@ skia::BenchmarkingCanvas benchmarking_canvas(&canvas); picture->picture->playback(&benchmarking_canvas); + v8::Local<v8::Context> context = isolate->GetCurrentContext(); v8::Local<v8::Array> op_times = v8::Array::New(isolate, benchmarking_canvas.CommandCount()); for (size_t i = 0; i < benchmarking_canvas.CommandCount(); ++i) { - op_times->Set(i, v8::Number::New(isolate, benchmarking_canvas.GetTime(i))); + op_times + ->Set(context, i, + v8::Number::New(isolate, benchmarking_canvas.GetTime(i))) + .Check(); } v8::Local<v8::Object> result = v8::Object::New(isolate); - result->Set(v8::String::NewFromUtf8(isolate, "total_time", - v8::NewStringType::kInternalized) - .ToLocalChecked(), - v8::Number::New(isolate, total_time.InMillisecondsF())); - result->Set(v8::String::NewFromUtf8(isolate, "cmd_times", - v8::NewStringType::kInternalized) - .ToLocalChecked(), - op_times); + result + ->Set(context, + v8::String::NewFromUtf8(isolate, "total_time", + v8::NewStringType::kInternalized) + .ToLocalChecked(), + v8::Number::New(isolate, total_time.InMillisecondsF())) + .Check(); + result + ->Set(context, + v8::String::NewFromUtf8(isolate, "cmd_times", + v8::NewStringType::kInternalized) + .ToLocalChecked(), + op_times) + .Check(); args->Return(result); } @@ -306,15 +319,22 @@ if (!picture.get()) return; + v8::Local<v8::Context> context = isolate->GetCurrentContext(); v8::Local<v8::Object> result = v8::Object::New(isolate); - result->Set(v8::String::NewFromUtf8(isolate, "width", - v8::NewStringType::kInternalized) - .ToLocalChecked(), - v8::Number::New(isolate, picture->layer_rect.width())); - result->Set(v8::String::NewFromUtf8(isolate, "height", - v8::NewStringType::kInternalized) - .ToLocalChecked(), - v8::Number::New(isolate, picture->layer_rect.height())); + result + ->Set(context, + v8::String::NewFromUtf8(isolate, "width", + v8::NewStringType::kInternalized) + .ToLocalChecked(), + v8::Number::New(isolate, picture->layer_rect.width())) + .Check(); + result + ->Set(context, + v8::String::NewFromUtf8(isolate, "height", + v8::NewStringType::kInternalized) + .ToLocalChecked(), + v8::Number::New(isolate, picture->layer_rect.height())) + .Check(); args->Return(result); }
diff --git a/content/renderer/stats_collection_controller.cc b/content/renderer/stats_collection_controller.cc index 8a62df4a..894c1fb 100644 --- a/content/renderer/stats_collection_controller.cc +++ b/content/renderer/stats_collection_controller.cc
@@ -42,8 +42,10 @@ if (controller.IsEmpty()) return; v8::Local<v8::Object> global = context->Global(); - global->Set(gin::StringToV8(isolate, "statsCollectionController"), - controller.ToV8()); + global + ->Set(context, gin::StringToV8(isolate, "statsCollectionController"), + controller.ToV8()) + .Check(); } StatsCollectionController::StatsCollectionController() {}
diff --git a/content/renderer/web_ui_extension.cc b/content/renderer/web_ui_extension.cc index 2e37ad5..5af8770 100644 --- a/content/renderer/web_ui_extension.cc +++ b/content/renderer/web_ui_extension.cc
@@ -74,16 +74,20 @@ v8::Context::Scope context_scope(context); v8::Local<v8::Object> chrome = GetOrCreateChromeObject(isolate, context); - chrome->Set( - gin::StringToSymbol(isolate, "send"), - gin::CreateFunctionTemplate(isolate, base::Bind(&WebUIExtension::Send)) - ->GetFunction(context) - .ToLocalChecked()); - chrome->Set(gin::StringToSymbol(isolate, "getVariableValue"), - gin::CreateFunctionTemplate( - isolate, base::Bind(&WebUIExtension::GetVariableValue)) - ->GetFunction(context) - .ToLocalChecked()); + chrome + ->Set(context, gin::StringToSymbol(isolate, "send"), + gin::CreateFunctionTemplate(isolate, + base::Bind(&WebUIExtension::Send)) + ->GetFunction(context) + .ToLocalChecked()) + .Check(); + chrome + ->Set(context, gin::StringToSymbol(isolate, "getVariableValue"), + gin::CreateFunctionTemplate( + isolate, base::Bind(&WebUIExtension::GetVariableValue)) + ->GetFunction(context) + .ToLocalChecked()) + .Check(); } // static
diff --git a/content/test/data/page_with_multiple_iframes.html b/content/test/data/page_with_multiple_iframes.html new file mode 100644 index 0000000..0f7e155 --- /dev/null +++ b/content/test/data/page_with_multiple_iframes.html
@@ -0,0 +1,11 @@ +<html> +<head></head> +<body> + <p>This page has several iframes. Yay for iframes!</p> + <p><iframe src="page_with_image.html" id="test_iframe_1"></iframe></p> + <p><iframe src="page_with_popup.html" id="test_iframe_2"></iframe></p> + <p><iframe src="page_with_frameset.html" id="test_iframe_3"></iframe></p> + <p><iframe src="page_with_allowfullscreen_frame.html" id="test_iframe_4"></iframe></p> + <p><iframe src="page_with_iframe_and_link.html" id="test_iframe_5"></iframe></p> +</body> +</html>
diff --git a/extensions/common/api/_manifest_features.json b/extensions/common/api/_manifest_features.json index 4acd353..e9928d24 100644 --- a/extensions/common/api/_manifest_features.json +++ b/extensions/common/api/_manifest_features.json
@@ -139,7 +139,10 @@ "file_handlers": [ { "channel": "stable", - "extension_types": ["platform_app"] + "extension_types": [ + "platform_app", + "hosted_app" // This should be removed when bookmark apps have migrated off hosted apps. + ] }, { "channel": "stable", "extension_types": [ "extension"],
diff --git a/extensions/common/manifest_constants.cc b/extensions/common/manifest_constants.cc index 81b0a3c..c40aded 100644 --- a/extensions/common/manifest_constants.cc +++ b/extensions/common/manifest_constants.cc
@@ -408,6 +408,8 @@ "Invalid value for 'file_filters[*]'."; const char kInvalidFileHandlers[] = "Invalid value for 'file_handlers'."; +const char kInvalidFileHandlersHostedAppsNotSupported[] = + "Hosted apps do not support file handlers"; const char kInvalidFileHandlersTooManyTypesAndExtensions[] = "Too many MIME and extension file_handlers have been declared."; const char kInvalidFileHandlerExtension[] =
diff --git a/extensions/common/manifest_constants.h b/extensions/common/manifest_constants.h index 5132846..3b45fc0 100644 --- a/extensions/common/manifest_constants.h +++ b/extensions/common/manifest_constants.h
@@ -329,6 +329,7 @@ extern const char kInvalidFileFiltersList[]; extern const char kInvalidFileFilterValue[]; extern const char kInvalidFileHandlers[]; +extern const char kInvalidFileHandlersHostedAppsNotSupported[]; extern const char kInvalidFileHandlersTooManyTypesAndExtensions[]; extern const char kInvalidFileHandlerExtension[]; extern const char kInvalidFileHandlerExtensionElement[];
diff --git a/extensions/common/manifest_handlers/file_handler_info.cc b/extensions/common/manifest_handlers/file_handler_info.cc index a33e848..bad091bb 100644 --- a/extensions/common/manifest_handlers/file_handler_info.cc +++ b/extensions/common/manifest_handlers/file_handler_info.cc
@@ -173,6 +173,17 @@ } bool FileHandlersParser::Parse(Extension* extension, base::string16* error) { + // Don't load file handlers for hosted_apps unless they're also bookmark apps. + // This check can be removed when bookmark apps are migrated off hosted apps, + // and hosted_apps should be removed from the list of valid extension types + // for "file_handling" in extensions/common/api/_manifest_features.json. + if (extension->is_hosted_app() && !extension->from_bookmark()) { + extension->AddInstallWarning( + InstallWarning(errors::kInvalidFileHandlersHostedAppsNotSupported, + keys::kFileHandlers)); + return true; + } + std::unique_ptr<FileHandlers> info(new FileHandlers); const base::Value* all_handlers = nullptr; if (!extension->manifest()->GetDictionary(keys::kFileHandlers,
diff --git a/extensions/common/manifest_handlers/file_handler_manifest_unittest.cc b/extensions/common/manifest_handlers/file_handler_manifest_unittest.cc index 75c336a6..aacce84 100644 --- a/extensions/common/manifest_handlers/file_handler_manifest_unittest.cc +++ b/extensions/common/manifest_handlers/file_handler_manifest_unittest.cc
@@ -2,7 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <vector> + #include "base/stl_util.h" +#include "extensions/common/install_warning.h" +#include "extensions/common/manifest.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/file_handler_info.h" #include "extensions/common/manifest_test.h" @@ -82,4 +86,44 @@ ASSERT_TRUE(handlers == NULL); } +TEST_F(FileHandlersManifestTest, HostedNotBookmarkApp) { + // This should load successfully but have the file handlers ignored. + scoped_refptr<const Extension> extension = LoadAndExpectSuccess( + "file_handlers_valid_hosted_app.json", extensions::Manifest::INTERNAL); + + ASSERT_TRUE(extension); + + std::vector<InstallWarning> expected_warnings; + expected_warnings.push_back( + InstallWarning(errors::kInvalidFileHandlersHostedAppsNotSupported)); + EXPECT_EQ(expected_warnings, extension->install_warnings()); + + EXPECT_TRUE(extension->is_hosted_app()); + EXPECT_FALSE(extension->from_bookmark()); + + const FileHandlersInfo* handlers = + FileHandlers::GetFileHandlers(extension.get()); + EXPECT_FALSE(handlers); +} + +TEST_F(FileHandlersManifestTest, HostedBookmarkApp) { + // This should load successfully with file handlers. + scoped_refptr<const Extension> extension = + LoadAndExpectSuccess("file_handlers_valid_hosted_app.json", + extensions::Manifest::Location::INTERNAL, + extensions::Extension::FROM_BOOKMARK); + + ASSERT_TRUE(extension); + EXPECT_TRUE(extension->install_warnings().empty()); + + // Check we're a hosted app and a bookmark app. + EXPECT_TRUE(extension->is_hosted_app()); + EXPECT_TRUE(extension->from_bookmark()); + + const FileHandlersInfo* handlers = + FileHandlers::GetFileHandlers(extension.get()); + ASSERT_TRUE(handlers); + EXPECT_GE(handlers->size(), 1u); +} + } // namespace extensions
diff --git a/extensions/test/data/manifest_tests/file_handlers_valid_hosted_app.json b/extensions/test/data/manifest_tests/file_handlers_valid_hosted_app.json new file mode 100644 index 0000000..e4fea5d --- /dev/null +++ b/extensions/test/data/manifest_tests/file_handlers_valid_hosted_app.json
@@ -0,0 +1,32 @@ +{ + "name": "test", + "manifest_version": 2, + "description": "App with file_handlers manifest.", + "version": "1", + "app": { + "launch": { + "web_url": "/" + } + }, + "file_handlers": { + "text": { + "types": [ + "text/*" + ] + }, + "image": { + "types": [ + "image/*" + ], + "extensions": [ + ".png", + ".gif" + ], + "verb": "add_to" + }, + "directories": { + "extensions": ["*/*"], + "include_directories": true + } + } +}
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc index e597994..5ca2706 100644 --- a/gpu/config/gpu_finch_features.cc +++ b/gpu/config/gpu_finch_features.cc
@@ -4,10 +4,30 @@ #include "gpu/config/gpu_finch_features.h" #if defined(OS_ANDROID) +#include "base/android/build_info.h" +#include "base/metrics/field_trial_params.h" +#include "base/strings/string_split.h" #include "ui/gl/android/android_surface_control_compat.h" #endif namespace features { +namespace { + +#if defined(OS_ANDROID) +bool FieldIsInBlacklist(const char* current_value, std::string blacklist_str) { + std::vector<std::string> blacklist = base::SplitString( + blacklist_str, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + for (const std::string& value : blacklist) { + if (value == current_value) + return true; + } + + return false; +} +#endif + +} // namespace + #if defined(OS_ANDROID) // Use android AImageReader when playing videos with MediaPlayer. const base::Feature kAImageReaderMediaPlayer{"AImageReaderMediaPlayer", @@ -80,8 +100,26 @@ #if defined(OS_ANDROID) bool IsAndroidSurfaceControlEnabled() { - return base::FeatureList::IsEnabled(kAndroidSurfaceControl) && - gl::SurfaceControl::IsSupported(); + if (!gl::SurfaceControl::IsSupported()) + return false; + + if (!base::FeatureList::IsEnabled(kAndroidSurfaceControl)) + return false; + + if (FieldIsInBlacklist(base::android::BuildInfo::GetInstance()->model(), + base::GetFieldTrialParamValueByFeature( + kAndroidSurfaceControl, "blacklisted_models"))) { + return false; + } + + if (FieldIsInBlacklist( + base::android::BuildInfo::GetInstance()->android_build_id(), + base::GetFieldTrialParamValueByFeature(kAndroidSurfaceControl, + "blacklisted_build_ids"))) { + return false; + } + + return true; } #endif
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc index c4a7a6c..b219525 100644 --- a/gpu/ipc/service/direct_composition_surface_win.cc +++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -16,6 +16,7 @@ #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/strings/stringprintf.h" #include "base/synchronization/waitable_event.h" #include "base/trace_event/trace_event.h" #include "base/win/scoped_handle.h" @@ -1053,6 +1054,21 @@ D3D11_TEXTURE2D_DESC texture_desc = {}; base::debug::Alias(&texture_desc); image_dxgi->texture()->GetDesc(&texture_desc); + static crash_reporter::CrashKeyString<32> texture_size_key( + "texture-size"); + texture_size_key.Set( + gfx::Size(texture_desc.Width, texture_desc.Height).ToString()); + static crash_reporter::CrashKeyString<16> texture_array_size_key( + "texture-array-size"); + texture_array_size_key.Set( + base::StringPrintf("%d", texture_desc.ArraySize)); + static crash_reporter::CrashKeyString<16> texture_bind_flags_key( + "texture-bind-flags"); + texture_bind_flags_key.Set( + base::StringPrintf("%#x", texture_desc.BindFlags)); + static crash_reporter::CrashKeyString<16> texture_usage_key( + "texture-usage-key"); + texture_usage_key.Set(base::StringPrintf("%#x", texture_desc.Usage)); base::debug::DumpWithoutCrashing(); return false; }
diff --git a/ios/chrome/browser/sync/profile_sync_service_factory_unittest.cc b/ios/chrome/browser/sync/profile_sync_service_factory_unittest.cc index 94771a4..63fb1ae 100644 --- a/ios/chrome/browser/sync/profile_sync_service_factory_unittest.cc +++ b/ios/chrome/browser/sync/profile_sync_service_factory_unittest.cc
@@ -43,7 +43,7 @@ protected: // Returns the collection of default datatypes. std::vector<syncer::ModelType> DefaultDatatypes() { - static_assert(44 == syncer::MODEL_TYPE_COUNT, + static_assert(44 == syncer::ModelType::NUM_ENTRIES, "When adding a new type, you probably want to add it here as " "well (assuming it is already enabled).");
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn index 525af18..c91a33b 100644 --- a/ios/chrome/browser/ui/browser_view/BUILD.gn +++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -145,6 +145,7 @@ "//ios/public/provider/chrome/browser/voice", "//ios/third_party/material_components_ios", "//ios/web", + "//ios/web/common", "//ios/web/public", "//third_party/google_toolbox_for_mac", "//ui/base",
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index 178ddfe..696e64e 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -189,10 +189,10 @@ #include "ios/public/provider/chrome/browser/voice/voice_search_controller.h" #include "ios/public/provider/chrome/browser/voice/voice_search_provider.h" #import "ios/third_party/material_components_ios/src/components/Snackbar/src/MaterialSnackbar.h" +#include "ios/web/common/referrer_util.h" #include "ios/web/public/features.h" #include "ios/web/public/navigation_item.h" #import "ios/web/public/navigation_manager.h" -#include "ios/web/public/referrer_util.h" #include "ios/web/public/url_scheme_util.h" #include "ios/web/public/user_agent.h" #include "ios/web/public/web_client.h"
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn index e8f2786..1456faa 100644 --- a/ios/chrome/browser/web/BUILD.gn +++ b/ios/chrome/browser/web/BUILD.gn
@@ -48,6 +48,7 @@ "//ios/chrome/browser/ui/util:util", "//ios/net", "//ios/web", + "//ios/web/common", "//ui/base", "//url", ]
diff --git a/ios/chrome/browser/web/image_fetch_tab_helper.mm b/ios/chrome/browser/web/image_fetch_tab_helper.mm index ec069fab..685fc9e 100644 --- a/ios/chrome/browser/web/image_fetch_tab_helper.mm +++ b/ios/chrome/browser/web/image_fetch_tab_helper.mm
@@ -12,8 +12,8 @@ #include "base/task/post_task.h" #include "base/values.h" #include "components/image_fetcher/ios/ios_image_data_fetcher_wrapper.h" +#include "ios/web/common/referrer_util.h" #include "ios/web/public/browser_state.h" -#include "ios/web/public/referrer_util.h" #import "ios/web/public/web_state/navigation_context.h" #include "ios/web/public/web_task_traits.h" #include "ios/web/public/web_thread.h"
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index ef60a30..d19dcea3 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -358,7 +358,6 @@ sources = [ "public/crw_session_certificate_policy_cache_storage_unittest.mm", "public/origin_util_unittest.mm", - "public/referrer_util_unittest.cc", "public/serializable_user_data_manager_unittest.mm", "public/ssl_status_unittest.cc", "public/user_agent_unittest.mm", @@ -379,6 +378,7 @@ "//ios/net", "//ios/testing:ocmock_support", "//ios/web", + "//ios/web/common", "//ios/web/find_in_page", "//ios/web/interstitials", "//ios/web/navigation",
diff --git a/ios/web/common/BUILD.gn b/ios/web/common/BUILD.gn index d146abf..4bac33b 100644 --- a/ios/web/common/BUILD.gn +++ b/ios/web/common/BUILD.gn
@@ -9,6 +9,8 @@ "crw_content_view.h", "crw_web_view_content_view.h", "crw_web_view_content_view.mm", + "referrer_util.cc", + "referrer_util.h", "url_util.cc", "url_util.h", ] @@ -16,6 +18,8 @@ deps = [ "//base", "//ios/web/public:features", + "//ios/web/public:referrer", + "//net", "//url", ] @@ -29,10 +33,15 @@ testonly = true deps = [ ":common", + "//base", + "//ios/web/public:referrer", + "//net", "//testing/gtest", + "//url", ] sources = [ + "referrer_util_unittest.cc", "url_util_unittest.cc", ] }
diff --git a/ios/web/common/DEPS b/ios/web/common/DEPS index f07d4508..a57d2fc 100644 --- a/ios/web/common/DEPS +++ b/ios/web/common/DEPS
@@ -2,6 +2,7 @@ # common interfaces cannot depend on private web code. "-ios/web", "+ios/web/common", + "+ios/web/public", ] specific_include_rules = {
diff --git a/ios/web/public/referrer_util.cc b/ios/web/common/referrer_util.cc similarity index 94% rename from ios/web/public/referrer_util.cc rename to ios/web/common/referrer_util.cc index f572293..01bf0dc 100644 --- a/ios/web/public/referrer_util.cc +++ b/ios/web/common/referrer_util.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 "ios/web/public/referrer_util.h" +#include "ios/web/common/referrer_util.h" #include "base/logging.h" #include "ios/web/public/referrer.h" @@ -10,9 +10,8 @@ namespace web { -std::string ReferrerHeaderValueForNavigation( - const GURL& destination, - const web::Referrer& referrer) { +std::string ReferrerHeaderValueForNavigation(const GURL& destination, + const web::Referrer& referrer) { bool is_downgrade = referrer.url.SchemeIsCryptographic() && !destination.SchemeIsCryptographic(); switch (referrer.policy) {
diff --git a/ios/web/public/referrer_util.h b/ios/web/common/referrer_util.h similarity index 81% rename from ios/web/public/referrer_util.h rename to ios/web/common/referrer_util.h index bcbdcbef..49ef082 100644 --- a/ios/web/public/referrer_util.h +++ b/ios/web/common/referrer_util.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_WEB_PUBLIC_REFERRER_UTIL_H_ -#define IOS_WEB_PUBLIC_REFERRER_UTIL_H_ +#ifndef IOS_WEB_COMMON_REFERRER_UTIL_H_ +#define IOS_WEB_COMMON_REFERRER_UTIL_H_ #include <string> @@ -17,9 +17,8 @@ // Returns the string that should be sent as the Referer header value for // navigating to |destination| from the given referrer, taking the referrer // policy into account. Returns an empty string if no Referer should be sent. -std::string ReferrerHeaderValueForNavigation( - const GURL& destination, - const web::Referrer& referrer); +std::string ReferrerHeaderValueForNavigation(const GURL& destination, + const web::Referrer& referrer); // Returns the policy that should be used to process subsequent forwards, if // any. @@ -36,4 +35,4 @@ } // namespace web -#endif // IOS_WEB_PUBLIC_REFERRER_UTIL_H_ +#endif // IOS_WEB_COMMON_REFERRER_UTIL_H_
diff --git a/ios/web/public/referrer_util_unittest.cc b/ios/web/common/referrer_util_unittest.cc similarity index 99% rename from ios/web/public/referrer_util_unittest.cc rename to ios/web/common/referrer_util_unittest.cc index 2330ec80..a8cca5a0 100644 --- a/ios/web/public/referrer_util_unittest.cc +++ b/ios/web/common/referrer_util_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 "ios/web/public/referrer_util.h" +#include "ios/web/common/referrer_util.h" #include "base/stl_util.h" #include "ios/web/public/referrer.h"
diff --git a/ios/web/public/BUILD.gn b/ios/web/public/BUILD.gn index 690ebbe..4a0e104 100644 --- a/ios/web/public/BUILD.gn +++ b/ios/web/public/BUILD.gn
@@ -7,6 +7,7 @@ source_set("public") { public_deps = [ ":features", + ":referrer", ":user_agent", "//net", "//services/network/public/cpp", @@ -45,9 +46,6 @@ "navigation_manager.h", "origin_util.h", "origin_util.mm", - "referrer.h", - "referrer_util.cc", - "referrer_util.h", "reload_type.h", "security_style.h", "serializable_user_data_manager.h", @@ -133,3 +131,16 @@ configs += [ "//build/config/compiler:enable_arc" ] } + +source_set("referrer") { + deps = [ + "//base", + "//url", + ] + + sources = [ + "referrer.h", + ] + + configs += [ "//build/config/compiler:enable_arc" ] +}
diff --git a/ios/web/shell/test/earl_grey/shell_actions.h b/ios/web/shell/test/earl_grey/shell_actions.h index 9081ede..b9f7b1e 100644 --- a/ios/web/shell/test/earl_grey/shell_actions.h +++ b/ios/web/shell/test/earl_grey/shell_actions.h
@@ -7,9 +7,10 @@ #include <string> -#import <EarlGrey/EarlGrey.h> +#import <Foundation/Foundation.h> -#include "ios/web/public/test/element_selector.h" +@class ElementSelector; +@protocol GREYAction; namespace web {
diff --git a/ios/web/shell/test/earl_grey/shell_actions.mm b/ios/web/shell/test/earl_grey/shell_actions.mm index b1dadb1..f7c33c5 100644 --- a/ios/web/shell/test/earl_grey/shell_actions.mm +++ b/ios/web/shell/test/earl_grey/shell_actions.mm
@@ -4,6 +4,8 @@ #import "ios/web/shell/test/earl_grey/shell_actions.h" +#import <EarlGrey/EarlGrey.h> + #import "ios/web/public/test/earl_grey/web_view_actions.h" #include "ios/web/public/test/element_selector.h" #import "ios/web/shell/test/app/web_shell_test_util.h"
diff --git a/ios/web/web_state/BUILD.gn b/ios/web/web_state/BUILD.gn index b5d82d3..ebfd098 100644 --- a/ios/web/web_state/BUILD.gn +++ b/ios/web/web_state/BUILD.gn
@@ -153,6 +153,7 @@ deps = [ "//base", "//components/url_formatter", + "//ios/web/common", "//ios/web/public", ]
diff --git a/ios/web/web_state/context_menu_params_utils.mm b/ios/web/web_state/context_menu_params_utils.mm index 52e4c542..d376851 100644 --- a/ios/web/web_state/context_menu_params_utils.mm +++ b/ios/web/web_state/context_menu_params_utils.mm
@@ -6,7 +6,7 @@ #include "base/strings/sys_string_conversions.h" #include "components/url_formatter/url_formatter.h" -#include "ios/web/public/referrer_util.h" +#include "ios/web/common/referrer_util.h" #import "ios/web/web_state/context_menu_constants.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/web/web_state/context_menu_params_utils_unittest.mm b/ios/web/web_state/context_menu_params_utils_unittest.mm index 76a65684..293cd23 100644 --- a/ios/web/web_state/context_menu_params_utils_unittest.mm +++ b/ios/web/web_state/context_menu_params_utils_unittest.mm
@@ -6,7 +6,7 @@ #include "base/strings/sys_string_conversions.h" #include "components/url_formatter/url_formatter.h" -#include "ios/web/public/referrer_util.h" +#include "ios/web/common/referrer_util.h" #import "ios/web/public/web_state/context_menu_params.h" #import "ios/web/web_state/context_menu_constants.h" #import "net/base/mac/url_conversions.h"
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 9007019..6974017 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -45,6 +45,7 @@ #import "ios/web/browsing_data/browsing_data_remover_observer.h" #import "ios/web/common/crw_content_view.h" #import "ios/web/common/crw_web_view_content_view.h" +#include "ios/web/common/referrer_util.h" #include "ios/web/common/url_util.h" #import "ios/web/find_in_page/find_in_page_manager_impl.h" #include "ios/web/history_state_util.h" @@ -66,7 +67,6 @@ #import "ios/web/public/navigation_item.h" #import "ios/web/public/navigation_manager.h" #include "ios/web/public/referrer.h" -#include "ios/web/public/referrer_util.h" #include "ios/web/public/ssl_status.h" #import "ios/web/public/url_scheme_util.h" #import "ios/web/public/web_client.h"
diff --git a/ios/web/web_state/web_state_unittest.mm b/ios/web/web_state/web_state_unittest.mm index c8b68d4..97ebd47 100644 --- a/ios/web/web_state/web_state_unittest.mm +++ b/ios/web/web_state/web_state_unittest.mm
@@ -334,11 +334,6 @@ // Verifies that large session can be restored. SlimNavigationManagder has max // session size limit of |wk_navigation_util::kMaxSessionSize|. TEST_P(WebStateTest, RestoreLargeSession) { -// TODO(crbug.com/946898): This test is failing on device with slim-nav enabled. -#if !TARGET_IPHONE_SIMULATOR - if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) - return; -#endif // Create session storage with large number of items. const int kItemCount = 150; NSMutableArray<CRWNavigationItemStorage*>* item_storages = @@ -355,6 +350,7 @@ CRWSessionStorage* session_storage = [[CRWSessionStorage alloc] init]; session_storage.itemStorages = item_storages; auto web_state = WebState::CreateWithStorageSession(params, session_storage); + web_state->SetKeepRenderProcessAlive(true); WebState* web_state_ptr = web_state.get(); NavigationManager* navigation_manager = web_state->GetNavigationManager(); // TODO(crbug.com/873729): The session will not be restored until
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index dde1433..66e8c0c 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -20,17 +20,6 @@ ] } -if (is_chromeos && use_v4lplugin) { - generate_stubs("libv4l2_stubs") { - extra_header = "v4l2/v4l2_stub_header.fragment" - sigs = [ "v4l2/v4l2.sig" ] - output_name = "v4l2/v4l2_stubs" - deps = [ - "//base", - ] - } -} - component("gpu") { output_name = "media_gpu" @@ -77,17 +66,12 @@ "gpu_video_decode_accelerator_factory.h", "gpu_video_encode_accelerator_factory.cc", "gpu_video_encode_accelerator_factory.h", - "image_processor.cc", - "image_processor.h", - "image_processor_factory.cc", - "image_processor_factory.h", - "libyuv_image_processor.cc", - "libyuv_image_processor.h", ] public_deps = [ ":buildflags", ":common", + ":image_processor", "//base", "//gpu", "//media", @@ -187,49 +171,8 @@ } } - if (use_v4lplugin) { - deps += [ ":libv4l2_stubs" ] - } - if (use_v4l2_codec) { - sources += [ - "v4l2/generic_v4l2_device.cc", - "v4l2/generic_v4l2_device.h", - "v4l2/v4l2_decode_surface.cc", - "v4l2/v4l2_decode_surface.h", - "v4l2/v4l2_decode_surface_handler.h", - "v4l2/v4l2_device.cc", - "v4l2/v4l2_device.h", - "v4l2/v4l2_h264_accelerator.cc", - "v4l2/v4l2_h264_accelerator.h", - "v4l2/v4l2_image_processor.cc", - "v4l2/v4l2_image_processor.h", - "v4l2/v4l2_jpeg_encode_accelerator.cc", - "v4l2/v4l2_jpeg_encode_accelerator.h", - "v4l2/v4l2_mjpeg_decode_accelerator.cc", - "v4l2/v4l2_mjpeg_decode_accelerator.h", - "v4l2/v4l2_slice_video_decode_accelerator.cc", - "v4l2/v4l2_slice_video_decode_accelerator.h", - "v4l2/v4l2_video_decode_accelerator.cc", - "v4l2/v4l2_video_decode_accelerator.h", - "v4l2/v4l2_video_encode_accelerator.cc", - "v4l2/v4l2_video_encode_accelerator.h", - "v4l2/v4l2_vp8_accelerator.cc", - "v4l2/v4l2_vp8_accelerator.h", - "v4l2/v4l2_vp9_accelerator.cc", - "v4l2/v4l2_vp9_accelerator.h", - ] - - libs = [ - "EGL", - "GLESv2", - ] - if (current_cpu == "arm") { - sources += [ - "v4l2/tegra_v4l2_device.cc", - "v4l2/tegra_v4l2_device.h", - ] - } + public_deps += [ "//media/gpu/v4l2" ] } if (use_vaapi) { @@ -347,6 +290,45 @@ ] } +source_set("image_processor") { + defines = [ "MEDIA_GPU_IMPLEMENTATION" ] + sources = [ + "image_processor_factory.cc", + "libyuv_image_processor.cc", + "libyuv_image_processor.h", + ] + + public_deps = [ + ":image_processor_common", + ] + + deps = [ + "//third_party/libyuv", + "//ui/gl", + ] + + if (use_v4l2_codec) { + deps += [ "//media/gpu/v4l2" ] + } +} + +source_set("image_processor_common") { + defines = [ "MEDIA_GPU_IMPLEMENTATION" ] + sources = [ + "image_processor.cc", + "image_processor.h", + "image_processor_factory.h", + ] + + public_deps = [ + ":buildflags", + ":common", + "//base", + "//media", + "//ui/gfx/geometry", + ] +} + # TODO(watk): Run this on bots. http://crbug.com/461437 if (is_win || is_android || use_v4l2_codec || use_vaapi) { test("video_decode_accelerator_unittest") { @@ -603,7 +585,7 @@ deps += [ "//media/gpu/vaapi:unit_test" ] } if (use_v4l2_codec) { - sources += [ "v4l2/v4l2_device_unittest.cc" ] + deps += [ "//media/gpu/v4l2:unit_test" ] } if (use_v4l2_codec || use_vaapi) { sources += [ "vp8_decoder_unittest.cc" ]
diff --git a/media/gpu/v4l2/BUILD.gn b/media/gpu/v4l2/BUILD.gn new file mode 100644 index 0000000..adc3078 --- /dev/null +++ b/media/gpu/v4l2/BUILD.gn
@@ -0,0 +1,98 @@ +# 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("//build/config/features.gni") +import("//build/config/ui.gni") +import("//media/gpu/args.gni") +import("//testing/test.gni") +import("//tools/generate_stubs/rules.gni") +import("//ui/gl/features.gni") +import("//ui/ozone/ozone.gni") + +assert(use_v4l2_codec) + +if (use_v4lplugin) { + generate_stubs("libv4l2_stubs") { + extra_header = "v4l2_stub_header.fragment" + sigs = [ "v4l2.sig" ] + output_name = "v4l2_stubs" + deps = [ + "//base", + ] + } +} + +source_set("v4l2") { + defines = [ "MEDIA_GPU_IMPLEMENTATION" ] + sources = [ + "generic_v4l2_device.cc", + "generic_v4l2_device.h", + "v4l2_decode_surface.cc", + "v4l2_decode_surface.h", + "v4l2_decode_surface_handler.h", + "v4l2_device.cc", + "v4l2_device.h", + "v4l2_h264_accelerator.cc", + "v4l2_h264_accelerator.h", + "v4l2_image_processor.cc", + "v4l2_image_processor.h", + "v4l2_jpeg_encode_accelerator.cc", + "v4l2_jpeg_encode_accelerator.h", + "v4l2_mjpeg_decode_accelerator.cc", + "v4l2_mjpeg_decode_accelerator.h", + "v4l2_slice_video_decode_accelerator.cc", + "v4l2_slice_video_decode_accelerator.h", + "v4l2_video_decode_accelerator.cc", + "v4l2_video_decode_accelerator.h", + "v4l2_video_encode_accelerator.cc", + "v4l2_video_encode_accelerator.h", + "v4l2_vp8_accelerator.cc", + "v4l2_vp8_accelerator.h", + "v4l2_vp9_accelerator.cc", + "v4l2_vp9_accelerator.h", + ] + + libs = [ + "EGL", + "GLESv2", + ] + + if (current_cpu == "arm") { + sources += [ + "tegra_v4l2_device.cc", + "tegra_v4l2_device.h", + ] + } + + configs += [ "//third_party/libyuv:libyuv_config" ] + + deps = [ + "//base", + "//gpu/ipc/service", + "//media", + "//media/gpu:buildflags", + "//media/gpu:common", + "//media/gpu:image_processor_common", + "//third_party/libyuv", + "//ui/gfx/geometry", + "//ui/ozone", + ] + + if (use_v4lplugin) { + deps += [ ":libv4l2_stubs" ] + } +} + +source_set("unit_test") { + testonly = true + sources = [ + "v4l2_device_unittest.cc", + ] + deps = [ + ":v4l2", + "//testing/gtest", + "//ui/gfx:test_support", + "//ui/gl", + ] +}
diff --git a/media/learning/impl/BUILD.gn b/media/learning/impl/BUILD.gn index 638014f..1400eee1 100644 --- a/media/learning/impl/BUILD.gn +++ b/media/learning/impl/BUILD.gn
@@ -35,8 +35,8 @@ "random_number_generator.h", "random_tree_trainer.cc", "random_tree_trainer.h", - "target_distribution.cc", - "target_distribution.h", + "target_histogram.cc", + "target_histogram.h", "training_algorithm.h", "voting_ensemble.cc", "voting_ensemble.h", @@ -69,7 +69,7 @@ "one_hot_unittest.cc", "random_number_generator_unittest.cc", "random_tree_trainer_unittest.cc", - "target_distribution_unittest.cc", + "target_histogram_unittest.cc", "test_random_number_generator.cc", "test_random_number_generator.h", ]
diff --git a/media/learning/impl/distribution_reporter.cc b/media/learning/impl/distribution_reporter.cc index 7643bbd..9213028 100644 --- a/media/learning/impl/distribution_reporter.cc +++ b/media/learning/impl/distribution_reporter.cc
@@ -32,8 +32,8 @@ public: RegressionReporter(const LearningTask& task) : DistributionReporter(task) {} - void OnPrediction(TargetDistribution observed, - TargetDistribution predicted) override { + void OnPrediction(TargetHistogram observed, + TargetHistogram predicted) override { DCHECK_EQ(task().target_description.ordering, LearningTask::Ordering::kNumeric); DCHECK(!task().uma_hacky_confusion_matrix.empty()); @@ -97,7 +97,7 @@ DistributionReporter::~DistributionReporter() = default; Model::PredictionCB DistributionReporter::GetPredictionCallback( - TargetDistribution observed) { + TargetHistogram observed) { return base::BindOnce(&DistributionReporter::OnPrediction, weak_factory_.GetWeakPtr(), observed); }
diff --git a/media/learning/impl/distribution_reporter.h b/media/learning/impl/distribution_reporter.h index b47ce61..aa2ef6e 100644 --- a/media/learning/impl/distribution_reporter.h +++ b/media/learning/impl/distribution_reporter.h
@@ -14,7 +14,7 @@ #include "base/optional.h" #include "media/learning/common/learning_task.h" #include "media/learning/impl/model.h" -#include "media/learning/impl/target_distribution.h" +#include "media/learning/impl/target_histogram.h" namespace media { namespace learning { @@ -31,8 +31,7 @@ // Returns a prediction CB that will be compared to |observed|. |observed| is // the total number of counts that we observed. - virtual Model::PredictionCB GetPredictionCallback( - TargetDistribution observed); + virtual Model::PredictionCB GetPredictionCallback(TargetHistogram observed); // Set the subset of features that is being used to train the model. This is // used for feature importance measuremnts. @@ -49,8 +48,8 @@ const LearningTask& task() const { return task_; } // Implemented by subclasses to report a prediction. - virtual void OnPrediction(TargetDistribution observed, - TargetDistribution predicted) = 0; + virtual void OnPrediction(TargetHistogram observed, + TargetHistogram predicted) = 0; const base::Optional<std::set<int>>& feature_indices() const { return feature_indices_;
diff --git a/media/learning/impl/distribution_reporter_unittest.cc b/media/learning/impl/distribution_reporter_unittest.cc index 3815d5c..7908c4e4 100644 --- a/media/learning/impl/distribution_reporter_unittest.cc +++ b/media/learning/impl/distribution_reporter_unittest.cc
@@ -33,13 +33,13 @@ const TargetValue Zero(0); const TargetValue One(1); - TargetDistribution observed; + TargetHistogram observed; // Observe an average of 2 / 3. observed[Zero] = 100; observed[One] = 200; auto cb = reporter_->GetPredictionCallback(observed); - TargetDistribution predicted; + TargetHistogram predicted; // Predict an average of 5 / 9. predicted[Zero] = 40; predicted[One] = 50;
diff --git a/media/learning/impl/extra_trees_trainer_unittest.cc b/media/learning/impl/extra_trees_trainer_unittest.cc index ad07000..d9e1897 100644 --- a/media/learning/impl/extra_trees_trainer_unittest.cc +++ b/media/learning/impl/extra_trees_trainer_unittest.cc
@@ -55,7 +55,7 @@ TrainingData empty; auto model = Train(task_, empty); EXPECT_NE(model.get(), nullptr); - EXPECT_EQ(model->PredictDistribution(FeatureVector()), TargetDistribution()); + EXPECT_EQ(model->PredictDistribution(FeatureVector()), TargetHistogram()); } TEST_P(ExtraTreesTest, FisherIrisDataset) { @@ -67,8 +67,7 @@ // Verify predictions on the training set, just for sanity. size_t num_correct = 0; for (const LabelledExample& example : training_data) { - TargetDistribution distribution = - model->PredictDistribution(example.features); + TargetHistogram distribution = model->PredictDistribution(example.features); TargetValue predicted_value; if (distribution.FindSingularMax(&predicted_value) && predicted_value == example.target_value) { @@ -102,8 +101,7 @@ auto model = Train(task_, training_data); // The singular max should be example_1. - TargetDistribution distribution = - model->PredictDistribution(example_1.features); + TargetHistogram distribution = model->PredictDistribution(example_1.features); TargetValue predicted_value; EXPECT_TRUE(distribution.FindSingularMax(&predicted_value)); EXPECT_EQ(predicted_value, example_1.target_value); @@ -135,8 +133,7 @@ auto model = Train(task_, training_data); // Make sure that the results are in the right range. - TargetDistribution distribution = - model->PredictDistribution(example_1.features); + TargetHistogram distribution = model->PredictDistribution(example_1.features); EXPECT_GT(distribution.Average(), example_1.target_value.value() * 0.95); EXPECT_LT(distribution.Average(), example_1.target_value.value() * 1.05); distribution = model->PredictDistribution(example_2.features); @@ -194,10 +191,10 @@ // the data is separable, it probably should be exact. for (auto& r_example : r_examples) { const FeatureVector& fv = r_example.features; - TargetDistribution c_dist = c_model->PredictDistribution(fv); + TargetHistogram c_dist = c_model->PredictDistribution(fv); EXPECT_LE(c_dist.Average(), r_example.target_value.value() * 1.05); EXPECT_GE(c_dist.Average(), r_example.target_value.value() * 0.95); - TargetDistribution r_dist = r_model->PredictDistribution(fv); + TargetHistogram r_dist = r_model->PredictDistribution(fv); EXPECT_LE(r_dist.Average(), r_example.target_value.value() * 1.05); EXPECT_GE(r_dist.Average(), r_example.target_value.value() * 0.95); }
diff --git a/media/learning/impl/learning_task_controller_impl.cc b/media/learning/impl/learning_task_controller_impl.cc index fb1540e..fc4597a 100644 --- a/media/learning/impl/learning_task_controller_impl.cc +++ b/media/learning/impl/learning_task_controller_impl.cc
@@ -85,10 +85,9 @@ // Once we have a model, see if we'd get |example| correct. if (model_ && reporter_) { - TargetDistribution predicted = - model_->PredictDistribution(example.features); + TargetHistogram predicted = model_->PredictDistribution(example.features); - TargetDistribution observed; + TargetHistogram observed; observed += example.target_value; reporter_->GetPredictionCallback(observed).Run(predicted); }
diff --git a/media/learning/impl/learning_task_controller_impl_unittest.cc b/media/learning/impl/learning_task_controller_impl_unittest.cc index 5c05b0a..1b5f6c5 100644 --- a/media/learning/impl/learning_task_controller_impl_unittest.cc +++ b/media/learning/impl/learning_task_controller_impl_unittest.cc
@@ -28,8 +28,8 @@ } protected: - void OnPrediction(TargetDistribution observed, - TargetDistribution predicted) override { + void OnPrediction(TargetHistogram observed, + TargetHistogram predicted) override { num_reported_++; if (observed == predicted) num_correct_++; @@ -46,9 +46,9 @@ FakeModel(TargetValue target) : target_(target) {} // Model - TargetDistribution PredictDistribution( + TargetHistogram PredictDistribution( const FeatureVector& features) override { - TargetDistribution dist; + TargetHistogram dist; dist += target_; return dist; }
diff --git a/media/learning/impl/lookup_table_trainer.cc b/media/learning/impl/lookup_table_trainer.cc index 4c698c7..57ebdbbc 100644 --- a/media/learning/impl/lookup_table_trainer.cc +++ b/media/learning/impl/lookup_table_trainer.cc
@@ -19,17 +19,16 @@ } // Model - TargetDistribution PredictDistribution( - const FeatureVector& instance) override { + TargetHistogram PredictDistribution(const FeatureVector& instance) override { auto iter = buckets_.find(instance); if (iter == buckets_.end()) - return TargetDistribution(); + return TargetHistogram(); return iter->second; } private: - std::map<FeatureVector, TargetDistribution> buckets_; + std::map<FeatureVector, TargetHistogram> buckets_; }; LookupTableTrainer::LookupTableTrainer() = default;
diff --git a/media/learning/impl/lookup_table_trainer_unittest.cc b/media/learning/impl/lookup_table_trainer_unittest.cc index 323d69d..4761874 100644 --- a/media/learning/impl/lookup_table_trainer_unittest.cc +++ b/media/learning/impl/lookup_table_trainer_unittest.cc
@@ -37,7 +37,7 @@ TrainingData empty; std::unique_ptr<Model> model = Train(task_, empty); EXPECT_NE(model.get(), nullptr); - EXPECT_EQ(model->PredictDistribution(FeatureVector()), TargetDistribution()); + EXPECT_EQ(model->PredictDistribution(FeatureVector()), TargetHistogram()); } TEST_F(LookupTableTrainerTest, UniformTrainingDataWorks) { @@ -51,8 +51,7 @@ // The tree should produce a distribution for one value (our target), which // has |n_examples| counts. - TargetDistribution distribution = - model->PredictDistribution(example.features); + TargetHistogram distribution = model->PredictDistribution(example.features); EXPECT_EQ(distribution.size(), 1u); EXPECT_EQ(distribution[example.target_value], n_examples); } @@ -66,8 +65,7 @@ std::unique_ptr<Model> model = Train(task_, training_data); // Each value should have a distribution with one target value with one count. - TargetDistribution distribution = - model->PredictDistribution(example_1.features); + TargetHistogram distribution = model->PredictDistribution(example_1.features); EXPECT_NE(model.get(), nullptr); EXPECT_EQ(distribution.size(), 1u); EXPECT_EQ(distribution[example_1.target_value], 1u); @@ -104,8 +102,7 @@ // Each example should have a distribution that selects the right value. for (const auto& example : training_data) { - TargetDistribution distribution = - model->PredictDistribution(example.features); + TargetHistogram distribution = model->PredictDistribution(example.features); TargetValue singular_max; EXPECT_TRUE(distribution.FindSingularMax(&singular_max)); EXPECT_EQ(singular_max, example.target_value); @@ -122,8 +119,7 @@ EXPECT_NE(model.get(), nullptr); // Each value should have a distribution with two targets with one count each. - TargetDistribution distribution = - model->PredictDistribution(example_1.features); + TargetHistogram distribution = model->PredictDistribution(example_1.features); EXPECT_EQ(distribution.size(), 2u); EXPECT_EQ(distribution[example_1.target_value], 1u); EXPECT_EQ(distribution[example_2.target_value], 1u); @@ -143,7 +139,7 @@ training_data.push_back(example_2); std::unique_ptr<Model> model = Train(task_, training_data); - TargetDistribution distribution = + TargetHistogram distribution = model->PredictDistribution(FeatureVector({FeatureValue(789)})); // OOV data should return an empty distribution (nominal). EXPECT_EQ(distribution.size(), 0u); @@ -160,7 +156,7 @@ training_data.push_back(example_2); std::unique_ptr<Model> model = Train(task_, training_data); - TargetDistribution distribution = + TargetHistogram distribution = model->PredictDistribution(FeatureVector({FeatureValue(123)})); double avg = distribution.Average(); const double expected =
diff --git a/media/learning/impl/model.h b/media/learning/impl/model.h index 0950b6c..4236687 100644 --- a/media/learning/impl/model.h +++ b/media/learning/impl/model.h
@@ -8,7 +8,7 @@ #include "base/component_export.h" #include "media/learning/common/labelled_example.h" #include "media/learning/impl/model.h" -#include "media/learning/impl/target_distribution.h" +#include "media/learning/impl/target_histogram.h" namespace media { namespace learning { @@ -19,11 +19,11 @@ class COMPONENT_EXPORT(LEARNING_IMPL) Model { public: // Callback for asynchronous predictions. - using PredictionCB = base::OnceCallback<void(TargetDistribution predicted)>; + using PredictionCB = base::OnceCallback<void(TargetHistogram predicted)>; virtual ~Model() = default; - virtual TargetDistribution PredictDistribution( + virtual TargetHistogram PredictDistribution( const FeatureVector& instance) = 0; // TODO(liberato): Consider adding an async prediction helper.
diff --git a/media/learning/impl/one_hot.cc b/media/learning/impl/one_hot.cc index b8dab81..c3e8285 100644 --- a/media/learning/impl/one_hot.cc +++ b/media/learning/impl/one_hot.cc
@@ -111,7 +111,7 @@ : converter_(std::move(converter)), model_(std::move(model)) {} ConvertingModel::~ConvertingModel() = default; -TargetDistribution ConvertingModel::PredictDistribution( +TargetHistogram ConvertingModel::PredictDistribution( const FeatureVector& instance) { FeatureVector converted_instance = converter_->Convert(instance); return model_->PredictDistribution(converted_instance);
diff --git a/media/learning/impl/one_hot.h b/media/learning/impl/one_hot.h index 0a3f479..b48b66e 100644 --- a/media/learning/impl/one_hot.h +++ b/media/learning/impl/one_hot.h
@@ -67,8 +67,7 @@ ~ConvertingModel() override; // Model - TargetDistribution PredictDistribution( - const FeatureVector& instance) override; + TargetHistogram PredictDistribution(const FeatureVector& instance) override; private: std::unique_ptr<OneHotConverter> converter_;
diff --git a/media/learning/impl/random_tree_trainer.cc b/media/learning/impl/random_tree_trainer.cc index 88e1b97..c45b757 100644 --- a/media/learning/impl/random_tree_trainer.cc +++ b/media/learning/impl/random_tree_trainer.cc
@@ -40,8 +40,7 @@ split_point_(split_point) {} // Model - TargetDistribution PredictDistribution( - const FeatureVector& features) override { + TargetHistogram PredictDistribution(const FeatureVector& features) override { // Figure out what feature value we should use for the split. FeatureValue f; switch (ordering_) { @@ -59,16 +58,16 @@ // If we've never seen this feature value, then return nothing. if (iter == children_.end()) - return TargetDistribution(); + return TargetHistogram(); return iter->second->PredictDistribution(features); } - TargetDistribution PredictDistributionWithMissingValues( + TargetHistogram PredictDistributionWithMissingValues( const FeatureVector& features) { - TargetDistribution total; + TargetHistogram total; for (auto& child_pair : children_) { - TargetDistribution predicted = + TargetHistogram predicted = child_pair.second->PredictDistribution(features); // TODO(liberato): Normalize? Weight? total += predicted; @@ -102,19 +101,26 @@ for (size_t idx : training_idx) distribution_ += training_data[idx]; - // Note that we don't treat numeric targets any differently. We want to - // weight the leaf by the number of examples, so replacing it with an - // average would just introduce rounding errors. One might as well take the - // average of the final distribution. + // Each leaf gets one vote. + // See https://en.wikipedia.org/wiki/Bootstrap_aggregating . TL;DR: the + // individual trees should average (regression) or vote (classification). + // + // TODO(liberato): It's unclear that a leaf should get to vote with an + // entire distribution; we might want to take the max for kUnordered here. + // If so, then we might also want to Average() for kNumeric targets, though + // in that case, the results would be the same anyway. That's not, of + // course, guaranteed for all methods of converting |distribution_| into a + // numeric prediction. In general, we should provide a single estimate. + distribution_.Normalize(); } // TreeNode - TargetDistribution PredictDistribution(const FeatureVector&) override { + TargetHistogram PredictDistribution(const FeatureVector&) override { return distribution_; } private: - TargetDistribution distribution_; + TargetHistogram distribution_; }; RandomTreeTrainer::RandomTreeTrainer(RandomNumberGenerator* rng) @@ -297,7 +303,8 @@ // Find the split's feature values and construct the training set for each. // I think we want to iterate on the underlying vector, and look up the int in - // the training data directly. + // the training data directly. |total_weight| will hold the total weight of + // all examples that come into this node. double total_weight = 0.; for (size_t idx : training_idx) { const LabelledExample& example = training_data[idx]; @@ -324,7 +331,7 @@ Split::BranchInfo& branch_info = iter->second; branch_info.training_idx.push_back(idx); - branch_info.target_distribution += example; + branch_info.target_histogram += example; } // Figure out how good / bad this split is. @@ -340,18 +347,22 @@ return split; } -void RandomTreeTrainer::ComputeSplitScore_Nominal(Split* split, - double total_weight) { +void RandomTreeTrainer::ComputeSplitScore_Nominal( + Split* split, + double total_incoming_weight) { // Compute the nats given that we're at this node. split->nats_remaining = 0; for (auto& info_iter : split->branch_infos) { Split::BranchInfo& branch_info = info_iter.second; - const double total_counts = branch_info.target_distribution.total_counts(); + // |weight_along_branch| is the total weight of examples that would follow + // this branch in the tree. + const double weight_along_branch = + branch_info.target_histogram.total_counts(); // |p_branch| is the probability of following this branch. - const double p_branch = total_counts / total_weight; - for (auto& iter : branch_info.target_distribution) { - double p = iter.second / total_counts; + const double p_branch = weight_along_branch / total_incoming_weight; + for (auto& iter : branch_info.target_histogram) { + double p = iter.second / total_incoming_weight; // p*log(p) is the expected nats if the answer is |iter|. We multiply // that by the probability of being in this bucket at all. split->nats_remaining -= (p * log(p)) * p_branch; @@ -359,25 +370,29 @@ } } -void RandomTreeTrainer::ComputeSplitScore_Numeric(Split* split, - double total_weight) { +void RandomTreeTrainer::ComputeSplitScore_Numeric( + Split* split, + double total_incoming_weight) { // Compute the nats given that we're at this node. split->nats_remaining = 0; for (auto& info_iter : split->branch_infos) { Split::BranchInfo& branch_info = info_iter.second; - const double total_counts = branch_info.target_distribution.total_counts(); + // |weight_along_branch| is the total weight of examples that would follow + // this branch in the tree. + const double weight_along_branch = + branch_info.target_histogram.total_counts(); // |p_branch| is the probability of following this branch. - const double p_branch = total_counts / total_weight; + const double p_branch = weight_along_branch / total_incoming_weight; // Compute the average at this node. Note that we have no idea if the leaf // node would actually use an average, but really it should match. It would - // be really nice if we could compute the value (or TargetDistribution) as + // be really nice if we could compute the value (or TargetHistogram) as // part of computing the split, and have somebody just hand that target // distribution to the leaf if it ends up as one. - double average = branch_info.target_distribution.Average(); + double average = branch_info.target_histogram.Average(); - for (auto& iter : branch_info.target_distribution) { + for (auto& iter : branch_info.target_histogram) { // Compute the squared error for all |iter.second| counts that each have a // value of |iter.first|, when this leaf approximates them as |average|. double sq_err = (iter.first.value() - average) *
diff --git a/media/learning/impl/random_tree_trainer.h b/media/learning/impl/random_tree_trainer.h index 3383e55..81646983 100644 --- a/media/learning/impl/random_tree_trainer.h +++ b/media/learning/impl/random_tree_trainer.h
@@ -20,7 +20,7 @@ namespace media { namespace learning { -// Trains RandomTree decision tree classifier (doesn't handle regression). +// Trains RandomTree decision tree classifier / regressor. // // Decision trees, including RandomTree, classify instances as follows. Each // non-leaf node is marked with a feature number |i|. The value of the |i|-th @@ -71,9 +71,9 @@ // See https://en.wikipedia.org/wiki/Random_forest for information. Note that // this is just a single tree, not the whole forest. // -// TODO(liberato): Right now, it not-so-randomly selects from the entire set. -// TODO(liberato): consider PRF or other simplified approximations. -// TODO(liberato): separate Model and TrainingAlgorithm. This is the latter. +// Note that this variant chooses split points randomly, as described by the +// ExtraTrees algorithm. This is slightly different than RandomForest, which +// chooses split points to improve the split's score. class COMPONENT_EXPORT(LEARNING_IMPL) RandomTreeTrainer : public TrainingAlgorithm, public HasRandomNumberGenerator { @@ -135,7 +135,7 @@ // branch of the split. // This is a flat_map since we're likely to have a very small (e.g., // "true / "false") number of targets. - TargetDistribution target_distribution; + TargetHistogram target_histogram; }; // [feature value at this split] = info about which examples take this @@ -158,12 +158,13 @@ const std::vector<size_t>& training_idx, int index); - // Fill in |nats_remaining| for |split| for a nominal target. |total_weight| - // is the total weight of all instances coming into this split. - void ComputeSplitScore_Nominal(Split* split, double total_weight); + // Fill in |nats_remaining| for |split| for a nominal target. + // |total_incoming_weight| is the total weight of all instances coming into + // the node that we're splitting. + void ComputeSplitScore_Nominal(Split* split, double total_incoming_weight); // Fill in |nats_remaining| for |split| for a numeric target. - void ComputeSplitScore_Numeric(Split* split, double total_weight); + void ComputeSplitScore_Numeric(Split* split, double total_incoming_weight); // Compute the split point for |training_data| for a nominal feature. FeatureValue FindSplitPoint_Nominal(size_t index,
diff --git a/media/learning/impl/random_tree_trainer_unittest.cc b/media/learning/impl/random_tree_trainer_unittest.cc index 6af9e94..f9face03 100644 --- a/media/learning/impl/random_tree_trainer_unittest.cc +++ b/media/learning/impl/random_tree_trainer_unittest.cc
@@ -55,7 +55,7 @@ TrainingData empty; std::unique_ptr<Model> model = Train(task_, empty); EXPECT_NE(model.get(), nullptr); - EXPECT_EQ(model->PredictDistribution(FeatureVector()), TargetDistribution()); + EXPECT_EQ(model->PredictDistribution(FeatureVector()), TargetHistogram()); } TEST_P(RandomTreeTest, UniformTrainingDataWorks) { @@ -69,11 +69,10 @@ std::unique_ptr<Model> model = Train(task_, training_data); // The tree should produce a distribution for one value (our target), which - // has |n_examples| counts. - TargetDistribution distribution = - model->PredictDistribution(example.features); + // has one count. + TargetHistogram distribution = model->PredictDistribution(example.features); EXPECT_EQ(distribution.size(), 1u); - EXPECT_EQ(distribution[example.target_value], n_examples); + EXPECT_EQ(distribution[example.target_value], 1.0); } TEST_P(RandomTreeTest, SimpleSeparableTrainingData) { @@ -86,8 +85,7 @@ std::unique_ptr<Model> model = Train(task_, training_data); // Each value should have a distribution with one target value with one count. - TargetDistribution distribution = - model->PredictDistribution(example_1.features); + TargetHistogram distribution = model->PredictDistribution(example_1.features); EXPECT_NE(model.get(), nullptr); EXPECT_EQ(distribution.size(), 1u); EXPECT_EQ(distribution[example_1.target_value], 1u); @@ -129,8 +127,7 @@ // Each example should have a distribution that selects the right value. for (const LabelledExample& example : training_data) { - TargetDistribution distribution = - model->PredictDistribution(example.features); + TargetHistogram distribution = model->PredictDistribution(example.features); TargetValue singular_max; EXPECT_TRUE(distribution.FindSingularMax(&singular_max)); EXPECT_EQ(singular_max, example.target_value); @@ -147,17 +144,16 @@ std::unique_ptr<Model> model = Train(task_, training_data); EXPECT_NE(model.get(), nullptr); - // Each value should have a distribution with two targets with one count each. - TargetDistribution distribution = - model->PredictDistribution(example_1.features); + // Each value should have a distribution with two targets with equal counts. + TargetHistogram distribution = model->PredictDistribution(example_1.features); EXPECT_EQ(distribution.size(), 2u); - EXPECT_EQ(distribution[example_1.target_value], 1u); - EXPECT_EQ(distribution[example_2.target_value], 1u); + EXPECT_EQ(distribution[example_1.target_value], 0.5); + EXPECT_EQ(distribution[example_2.target_value], 0.5); distribution = model->PredictDistribution(example_2.features); EXPECT_EQ(distribution.size(), 2u); - EXPECT_EQ(distribution[example_1.target_value], 1u); - EXPECT_EQ(distribution[example_2.target_value], 1u); + EXPECT_EQ(distribution[example_1.target_value], 0.5); + EXPECT_EQ(distribution[example_2.target_value], 0.5); } TEST_P(RandomTreeTest, UnknownFeatureValueHandling) { @@ -202,7 +198,7 @@ std::unique_ptr<Model> model = Train(task_, training_data); for (size_t i = 0; i < 4; i++) { // Get a prediction for the |i|-th feature value. - TargetDistribution distribution = model->PredictDistribution( + TargetHistogram distribution = model->PredictDistribution( FeatureVector({FeatureValue(i * feature_mult)})); // The distribution should have one count that should be correct. If // the feature isn't split four times, then some feature value will have too
diff --git a/media/learning/impl/target_distribution.cc b/media/learning/impl/target_distribution.cc deleted file mode 100644 index 2fe27173..0000000 --- a/media/learning/impl/target_distribution.cc +++ /dev/null
@@ -1,118 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/learning/impl/target_distribution.h" - -#include <sstream> - -namespace media { -namespace learning { - -TargetDistribution::TargetDistribution() = default; - -TargetDistribution::TargetDistribution(const TargetDistribution& rhs) = default; - -TargetDistribution::TargetDistribution(TargetDistribution&& rhs) = default; - -TargetDistribution::~TargetDistribution() = default; - -TargetDistribution& TargetDistribution::operator=( - const TargetDistribution& rhs) = default; - -TargetDistribution& TargetDistribution::operator=(TargetDistribution&& rhs) = - default; - -bool TargetDistribution::operator==(const TargetDistribution& rhs) const { - return rhs.total_counts() == total_counts() && rhs.counts_ == counts_; -} - -TargetDistribution& TargetDistribution::operator+=( - const TargetDistribution& rhs) { - for (auto& rhs_pair : rhs.counts()) - counts_[rhs_pair.first] += rhs_pair.second; - - return *this; -} - -TargetDistribution& TargetDistribution::operator+=(const TargetValue& rhs) { - counts_[rhs]++; - return *this; -} - -TargetDistribution& TargetDistribution::operator+=( - const LabelledExample& example) { - counts_[example.target_value] += example.weight; - return *this; -} - -size_t TargetDistribution::operator[](const TargetValue& value) const { - auto iter = counts_.find(value); - if (iter == counts_.end()) - return 0; - - return iter->second; -} - -size_t& TargetDistribution::operator[](const TargetValue& value) { - return counts_[value]; -} - -bool TargetDistribution::FindSingularMax(TargetValue* value_out, - size_t* counts_out) const { - if (!counts_.size()) - return false; - - size_t unused_counts; - if (!counts_out) - counts_out = &unused_counts; - - auto iter = counts_.begin(); - *value_out = iter->first; - *counts_out = iter->second; - bool singular_max = true; - for (iter++; iter != counts_.end(); iter++) { - if (iter->second > *counts_out) { - *value_out = iter->first; - *counts_out = iter->second; - singular_max = true; - } else if (iter->second == *counts_out) { - // If this turns out to be the max, then it's not singular. - singular_max = false; - } - } - - return singular_max; -} - -double TargetDistribution::Average() const { - double total_value = 0.; - size_t total_counts = 0; - for (auto& iter : counts_) { - total_value += iter.first.value() * iter.second; - total_counts += iter.second; - } - - if (!total_counts) - return 0.; - - return total_value / total_counts; -} - -std::string TargetDistribution::ToString() const { - std::ostringstream ss; - ss << "["; - for (auto& entry : counts_) - ss << " " << entry.first << ":" << entry.second; - ss << " ]"; - - return ss.str(); -} - -std::ostream& operator<<(std::ostream& out, - const media::learning::TargetDistribution& dist) { - return out << dist.ToString(); -} - -} // namespace learning -} // namespace media
diff --git a/media/learning/impl/target_distribution.h b/media/learning/impl/target_distribution.h deleted file mode 100644 index 3f4a9cd..0000000 --- a/media/learning/impl/target_distribution.h +++ /dev/null
@@ -1,94 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_LEARNING_IMPL_TARGET_DISTRIBUTION_H_ -#define MEDIA_LEARNING_IMPL_TARGET_DISTRIBUTION_H_ - -#include <ostream> -#include <string> - -#include "base/component_export.h" -#include "base/containers/flat_map.h" -#include "base/macros.h" -#include "media/learning/common/labelled_example.h" -#include "media/learning/common/value.h" - -namespace media { -namespace learning { - -// TargetDistribution of target values. -class COMPONENT_EXPORT(LEARNING_IMPL) TargetDistribution { - private: - // We use a flat_map since this will often have only one or two TargetValues, - // such as "true" or "false". - using DistributionMap = base::flat_map<TargetValue, size_t>; - - public: - TargetDistribution(); - TargetDistribution(const TargetDistribution& rhs); - TargetDistribution(TargetDistribution&& rhs); - ~TargetDistribution(); - - TargetDistribution& operator=(const TargetDistribution& rhs); - TargetDistribution& operator=(TargetDistribution&& rhs); - - bool operator==(const TargetDistribution& rhs) const; - - // Add |rhs| to our counts. - TargetDistribution& operator+=(const TargetDistribution& rhs); - - // Increment |rhs| by one. - TargetDistribution& operator+=(const TargetValue& rhs); - - // Increment the distribution by |example|'s target value and weight. - TargetDistribution& operator+=(const LabelledExample& example); - - // Return the number of counts for |value|. - size_t operator[](const TargetValue& value) const; - size_t& operator[](const TargetValue& value); - - // Return the total counts in the map. - size_t total_counts() const { - size_t total = 0.; - for (auto& entry : counts_) - total += entry.second; - return total; - } - - DistributionMap::const_iterator begin() const { return counts_.begin(); } - - DistributionMap::const_iterator end() const { return counts_.end(); } - - // Return the number of buckets in the distribution. - // TODO(liberato): Do we want this? - size_t size() const { return counts_.size(); } - - // Find the singular value with the highest counts, and copy it into - // |value_out| and (optionally) |counts_out|. Returns true if there is a - // singular maximum, else returns false with the out params undefined. - bool FindSingularMax(TargetValue* value_out, - size_t* counts_out = nullptr) const; - - // Return the average value of the entries in this distribution. Of course, - // this only makes sense if the TargetValues can be interpreted as numeric. - double Average() const; - - std::string ToString() const; - - private: - const DistributionMap& counts() const { return counts_; } - - // [value] == counts - DistributionMap counts_; - - // Allow copy and assign. -}; - -COMPONENT_EXPORT(LEARNING_IMPL) -std::ostream& operator<<(std::ostream& out, const TargetDistribution& dist); - -} // namespace learning -} // namespace media - -#endif // MEDIA_LEARNING_IMPL_TARGET_DISTRIBUTION_H_
diff --git a/media/learning/impl/target_distribution_unittest.cc b/media/learning/impl/target_distribution_unittest.cc deleted file mode 100644 index 1c7564a..0000000 --- a/media/learning/impl/target_distribution_unittest.cc +++ /dev/null
@@ -1,164 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/learning/impl/target_distribution.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace media { -namespace learning { - -class TargetDistributionTest : public testing::Test { - public: - TargetDistributionTest() : value_1(123), value_2(456), value_3(789) {} - - TargetDistribution distribution_; - - TargetValue value_1; - const size_t counts_1 = 100; - - TargetValue value_2; - const size_t counts_2 = 10; - - TargetValue value_3; -}; - -TEST_F(TargetDistributionTest, EmptyTargetDistributionHasZeroCounts) { - EXPECT_EQ(distribution_.total_counts(), 0u); -} - -TEST_F(TargetDistributionTest, AddingCountsWorks) { - distribution_[value_1] = counts_1; - EXPECT_EQ(distribution_.total_counts(), counts_1); - EXPECT_EQ(distribution_[value_1], counts_1); - distribution_[value_1] += counts_1; - EXPECT_EQ(distribution_.total_counts(), counts_1 * 2u); - EXPECT_EQ(distribution_[value_1], counts_1 * 2u); -} - -TEST_F(TargetDistributionTest, MultipleValuesAreSeparate) { - distribution_[value_1] = counts_1; - distribution_[value_2] = counts_2; - EXPECT_EQ(distribution_.total_counts(), counts_1 + counts_2); - EXPECT_EQ(distribution_[value_1], counts_1); - EXPECT_EQ(distribution_[value_2], counts_2); -} - -TEST_F(TargetDistributionTest, AddingTargetValues) { - distribution_ += value_1; - EXPECT_EQ(distribution_.total_counts(), 1u); - EXPECT_EQ(distribution_[value_1], 1u); - EXPECT_EQ(distribution_[value_2], 0u); - - distribution_ += value_1; - EXPECT_EQ(distribution_.total_counts(), 2u); - EXPECT_EQ(distribution_[value_1], 2u); - EXPECT_EQ(distribution_[value_2], 0u); - - distribution_ += value_2; - EXPECT_EQ(distribution_.total_counts(), 3u); - EXPECT_EQ(distribution_[value_1], 2u); - EXPECT_EQ(distribution_[value_2], 1u); -} - -TEST_F(TargetDistributionTest, AddingTargetDistributions) { - distribution_[value_1] = counts_1; - - TargetDistribution rhs; - rhs[value_2] = counts_2; - - distribution_ += rhs; - - EXPECT_EQ(distribution_.total_counts(), counts_1 + counts_2); - EXPECT_EQ(distribution_[value_1], counts_1); - EXPECT_EQ(distribution_[value_2], counts_2); -} - -TEST_F(TargetDistributionTest, FindSingularMaxFindsTheSingularMax) { - distribution_[value_1] = counts_1; - distribution_[value_2] = counts_2; - ASSERT_TRUE(counts_1 > counts_2); - - TargetValue max_value(0); - size_t max_counts = 0; - EXPECT_TRUE(distribution_.FindSingularMax(&max_value, &max_counts)); - EXPECT_EQ(max_value, value_1); - EXPECT_EQ(max_counts, counts_1); -} - -TEST_F(TargetDistributionTest, - FindSingularMaxFindsTheSingularMaxAlternateOrder) { - // Switch the order, to handle sorting in different directions. - distribution_[value_1] = counts_2; - distribution_[value_2] = counts_1; - ASSERT_TRUE(counts_1 > counts_2); - - TargetValue max_value(0); - size_t max_counts = 0; - EXPECT_TRUE(distribution_.FindSingularMax(&max_value, &max_counts)); - EXPECT_EQ(max_value, value_2); - EXPECT_EQ(max_counts, counts_1); -} - -TEST_F(TargetDistributionTest, FindSingularMaxReturnsFalsForNonSingularMax) { - distribution_[value_1] = counts_1; - distribution_[value_2] = counts_1; - - TargetValue max_value(0); - size_t max_counts = 0; - EXPECT_FALSE(distribution_.FindSingularMax(&max_value, &max_counts)); -} - -TEST_F(TargetDistributionTest, FindSingularMaxIgnoresNonSingularNonMax) { - distribution_[value_1] = counts_1; - // |value_2| and |value_3| are tied, but not the max. - distribution_[value_2] = counts_2; - distribution_[value_3] = counts_2; - ASSERT_TRUE(counts_1 > counts_2); - - TargetValue max_value(0); - size_t max_counts = 0; - EXPECT_TRUE(distribution_.FindSingularMax(&max_value, &max_counts)); - EXPECT_EQ(max_value, value_1); - EXPECT_EQ(max_counts, counts_1); -} - -TEST_F(TargetDistributionTest, FindSingularMaxDoesntRequireCounts) { - distribution_[value_1] = counts_1; - - TargetValue max_value(0); - EXPECT_TRUE(distribution_.FindSingularMax(&max_value)); - EXPECT_EQ(max_value, value_1); -} - -TEST_F(TargetDistributionTest, EqualDistributionsCompareAsEqual) { - distribution_[value_1] = counts_1; - TargetDistribution distribution_2; - distribution_2[value_1] = counts_1; - - EXPECT_TRUE(distribution_ == distribution_2); -} - -TEST_F(TargetDistributionTest, UnequalDistributionsCompareAsNotEqual) { - distribution_[value_1] = counts_1; - TargetDistribution distribution_2; - distribution_2[value_2] = counts_2; - - EXPECT_FALSE(distribution_ == distribution_2); -} - -TEST_F(TargetDistributionTest, WeightedLabelledExamplesCountCorrectly) { - LabelledExample example = {{}, value_1}; - example.weight = counts_1; - distribution_ += example; - - TargetDistribution distribution_2; - for (size_t i = 0; i < counts_1; i++) - distribution_2 += value_1; - - EXPECT_EQ(distribution_, distribution_2); -} - -} // namespace learning -} // namespace media
diff --git a/media/learning/impl/target_histogram.cc b/media/learning/impl/target_histogram.cc new file mode 100644 index 0000000..ad1a1f2 --- /dev/null +++ b/media/learning/impl/target_histogram.cc
@@ -0,0 +1,121 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/learning/impl/target_histogram.h" + +#include <sstream> + +namespace media { +namespace learning { + +TargetHistogram::TargetHistogram() = default; + +TargetHistogram::TargetHistogram(const TargetHistogram& rhs) = default; + +TargetHistogram::TargetHistogram(TargetHistogram&& rhs) = default; + +TargetHistogram::~TargetHistogram() = default; + +TargetHistogram& TargetHistogram::operator=(const TargetHistogram& rhs) = + default; + +TargetHistogram& TargetHistogram::operator=(TargetHistogram&& rhs) = default; + +bool TargetHistogram::operator==(const TargetHistogram& rhs) const { + return rhs.total_counts() == total_counts() && rhs.counts_ == counts_; +} + +TargetHistogram& TargetHistogram::operator+=(const TargetHistogram& rhs) { + for (auto& rhs_pair : rhs.counts()) + counts_[rhs_pair.first] += rhs_pair.second; + + return *this; +} + +TargetHistogram& TargetHistogram::operator+=(const TargetValue& rhs) { + counts_[rhs]++; + return *this; +} + +TargetHistogram& TargetHistogram::operator+=(const LabelledExample& example) { + counts_[example.target_value] += example.weight; + return *this; +} + +double TargetHistogram::operator[](const TargetValue& value) const { + auto iter = counts_.find(value); + if (iter == counts_.end()) + return 0; + + return iter->second; +} + +double& TargetHistogram::operator[](const TargetValue& value) { + return counts_[value]; +} + +bool TargetHistogram::FindSingularMax(TargetValue* value_out, + double* counts_out) const { + if (!counts_.size()) + return false; + + double unused_counts; + if (!counts_out) + counts_out = &unused_counts; + + auto iter = counts_.begin(); + *value_out = iter->first; + *counts_out = iter->second; + bool singular_max = true; + for (iter++; iter != counts_.end(); iter++) { + if (iter->second > *counts_out) { + *value_out = iter->first; + *counts_out = iter->second; + singular_max = true; + } else if (iter->second == *counts_out) { + // If this turns out to be the max, then it's not singular. + singular_max = false; + } + } + + return singular_max; +} + +double TargetHistogram::Average() const { + double total_value = 0.; + double total_counts = 0; + for (auto& iter : counts_) { + total_value += iter.first.value() * iter.second; + total_counts += iter.second; + } + + if (!total_counts) + return 0.; + + return total_value / total_counts; +} + +void TargetHistogram::Normalize() { + double total = total_counts(); + for (auto& iter : counts_) + iter.second /= total; +} + +std::string TargetHistogram::ToString() const { + std::ostringstream ss; + ss << "["; + for (auto& entry : counts_) + ss << " " << entry.first << ":" << entry.second; + ss << " ]"; + + return ss.str(); +} + +std::ostream& operator<<(std::ostream& out, + const media::learning::TargetHistogram& dist) { + return out << dist.ToString(); +} + +} // namespace learning +} // namespace media
diff --git a/media/learning/impl/target_histogram.h b/media/learning/impl/target_histogram.h new file mode 100644 index 0000000..cb8de2b6 --- /dev/null +++ b/media/learning/impl/target_histogram.h
@@ -0,0 +1,98 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_LEARNING_IMPL_TARGET_HISTOGRAM_H_ +#define MEDIA_LEARNING_IMPL_TARGET_HISTOGRAM_H_ + +#include <ostream> +#include <string> + +#include "base/component_export.h" +#include "base/containers/flat_map.h" +#include "base/macros.h" +#include "media/learning/common/labelled_example.h" +#include "media/learning/common/value.h" + +namespace media { +namespace learning { + +// Histogram of target values that allows fractional counts. +class COMPONENT_EXPORT(LEARNING_IMPL) TargetHistogram { + private: + // We use a flat_map since this will often have only one or two TargetValues, + // such as "true" or "false". + using CountMap = base::flat_map<TargetValue, double>; + + public: + TargetHistogram(); + TargetHistogram(const TargetHistogram& rhs); + TargetHistogram(TargetHistogram&& rhs); + ~TargetHistogram(); + + TargetHistogram& operator=(const TargetHistogram& rhs); + TargetHistogram& operator=(TargetHistogram&& rhs); + + bool operator==(const TargetHistogram& rhs) const; + + // Add |rhs| to our counts. + TargetHistogram& operator+=(const TargetHistogram& rhs); + + // Increment |rhs| by one. + TargetHistogram& operator+=(const TargetValue& rhs); + + // Increment the histogram by |example|'s target value and weight. + TargetHistogram& operator+=(const LabelledExample& example); + + // Return the number of counts for |value|. + double operator[](const TargetValue& value) const; + double& operator[](const TargetValue& value); + + // Return the total counts in the map. + double total_counts() const { + double total = 0.; + for (auto& entry : counts_) + total += entry.second; + return total; + } + + CountMap::const_iterator begin() const { return counts_.begin(); } + + CountMap::const_iterator end() const { return counts_.end(); } + + // Return the number of buckets in the histogram. + // TODO(liberato): Do we want this? + size_t size() const { return counts_.size(); } + + // Find the singular value with the highest counts, and copy it into + // |value_out| and (optionally) |counts_out|. Returns true if there is a + // singular maximum, else returns false with the out params undefined. + bool FindSingularMax(TargetValue* value_out, + double* counts_out = nullptr) const; + + // Return the average value of the entries in this histogram. Of course, + // this only makes sense if the TargetValues can be interpreted as numeric. + double Average() const; + + // Normalize the histogram so that it has one total count, unless it's + // empty. It will continue to have zero in that case. + void Normalize(); + + std::string ToString() const; + + private: + const CountMap& counts() const { return counts_; } + + // [value] == counts + CountMap counts_; + + // Allow copy and assign. +}; + +COMPONENT_EXPORT(LEARNING_IMPL) +std::ostream& operator<<(std::ostream& out, const TargetHistogram& dist); + +} // namespace learning +} // namespace media + +#endif // MEDIA_LEARNING_IMPL_TARGET_HISTOGRAM_H_
diff --git a/media/learning/impl/target_histogram_unittest.cc b/media/learning/impl/target_histogram_unittest.cc new file mode 100644 index 0000000..5ba36e0 --- /dev/null +++ b/media/learning/impl/target_histogram_unittest.cc
@@ -0,0 +1,179 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/learning/impl/target_histogram.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { +namespace learning { + +class TargetHistogramTest : public testing::Test { + public: + TargetHistogramTest() : value_1(123), value_2(456), value_3(789) {} + + TargetHistogram histogram_; + + TargetValue value_1; + const size_t counts_1 = 100; + + TargetValue value_2; + const size_t counts_2 = 10; + + TargetValue value_3; +}; + +TEST_F(TargetHistogramTest, EmptyTargetHistogramHasZeroCounts) { + EXPECT_EQ(histogram_.total_counts(), 0u); +} + +TEST_F(TargetHistogramTest, AddingCountsWorks) { + histogram_[value_1] = counts_1; + EXPECT_EQ(histogram_.total_counts(), counts_1); + EXPECT_EQ(histogram_[value_1], counts_1); + histogram_[value_1] += counts_1; + EXPECT_EQ(histogram_.total_counts(), counts_1 * 2u); + EXPECT_EQ(histogram_[value_1], counts_1 * 2u); +} + +TEST_F(TargetHistogramTest, MultipleValuesAreSeparate) { + histogram_[value_1] = counts_1; + histogram_[value_2] = counts_2; + EXPECT_EQ(histogram_.total_counts(), counts_1 + counts_2); + EXPECT_EQ(histogram_[value_1], counts_1); + EXPECT_EQ(histogram_[value_2], counts_2); +} + +TEST_F(TargetHistogramTest, AddingTargetValues) { + histogram_ += value_1; + EXPECT_EQ(histogram_.total_counts(), 1u); + EXPECT_EQ(histogram_[value_1], 1u); + EXPECT_EQ(histogram_[value_2], 0u); + + histogram_ += value_1; + EXPECT_EQ(histogram_.total_counts(), 2u); + EXPECT_EQ(histogram_[value_1], 2u); + EXPECT_EQ(histogram_[value_2], 0u); + + histogram_ += value_2; + EXPECT_EQ(histogram_.total_counts(), 3u); + EXPECT_EQ(histogram_[value_1], 2u); + EXPECT_EQ(histogram_[value_2], 1u); +} + +TEST_F(TargetHistogramTest, AddingTargetHistograms) { + histogram_[value_1] = counts_1; + + TargetHistogram rhs; + rhs[value_2] = counts_2; + + histogram_ += rhs; + + EXPECT_EQ(histogram_.total_counts(), counts_1 + counts_2); + EXPECT_EQ(histogram_[value_1], counts_1); + EXPECT_EQ(histogram_[value_2], counts_2); +} + +TEST_F(TargetHistogramTest, FindSingularMaxFindsTheSingularMax) { + histogram_[value_1] = counts_1; + histogram_[value_2] = counts_2; + ASSERT_TRUE(counts_1 > counts_2); + + TargetValue max_value(0); + double max_counts = 0; + EXPECT_TRUE(histogram_.FindSingularMax(&max_value, &max_counts)); + EXPECT_EQ(max_value, value_1); + EXPECT_EQ(max_counts, counts_1); +} + +TEST_F(TargetHistogramTest, FindSingularMaxFindsTheSingularMaxAlternateOrder) { + // Switch the order, to handle sorting in different directions. + histogram_[value_1] = counts_2; + histogram_[value_2] = counts_1; + ASSERT_TRUE(counts_1 > counts_2); + + TargetValue max_value(0); + double max_counts = 0; + EXPECT_TRUE(histogram_.FindSingularMax(&max_value, &max_counts)); + EXPECT_EQ(max_value, value_2); + EXPECT_EQ(max_counts, counts_1); +} + +TEST_F(TargetHistogramTest, FindSingularMaxReturnsFalsForNonSingularMax) { + histogram_[value_1] = counts_1; + histogram_[value_2] = counts_1; + + TargetValue max_value(0); + double max_counts = 0; + EXPECT_FALSE(histogram_.FindSingularMax(&max_value, &max_counts)); +} + +TEST_F(TargetHistogramTest, FindSingularMaxIgnoresNonSingularNonMax) { + histogram_[value_1] = counts_1; + // |value_2| and |value_3| are tied, but not the max. + histogram_[value_2] = counts_2; + histogram_[value_3] = counts_2; + ASSERT_TRUE(counts_1 > counts_2); + + TargetValue max_value(0); + double max_counts = 0; + EXPECT_TRUE(histogram_.FindSingularMax(&max_value, &max_counts)); + EXPECT_EQ(max_value, value_1); + EXPECT_EQ(max_counts, counts_1); +} + +TEST_F(TargetHistogramTest, FindSingularMaxDoesntRequireCounts) { + histogram_[value_1] = counts_1; + + TargetValue max_value(0); + EXPECT_TRUE(histogram_.FindSingularMax(&max_value)); + EXPECT_EQ(max_value, value_1); +} + +TEST_F(TargetHistogramTest, EqualDistributionsCompareAsEqual) { + histogram_[value_1] = counts_1; + TargetHistogram histogram_2; + histogram_2[value_1] = counts_1; + + EXPECT_TRUE(histogram_ == histogram_2); +} + +TEST_F(TargetHistogramTest, UnequalDistributionsCompareAsNotEqual) { + histogram_[value_1] = counts_1; + TargetHistogram histogram_2; + histogram_2[value_2] = counts_2; + + EXPECT_FALSE(histogram_ == histogram_2); +} + +TEST_F(TargetHistogramTest, WeightedLabelledExamplesCountCorrectly) { + LabelledExample example = {{}, value_1}; + example.weight = counts_1; + histogram_ += example; + + TargetHistogram histogram_2; + for (size_t i = 0; i < counts_1; i++) + histogram_2 += value_1; + + EXPECT_EQ(histogram_, histogram_2); +} + +TEST_F(TargetHistogramTest, Normalize) { + histogram_[value_1] = counts_1; + histogram_[value_2] = counts_2; + histogram_.Normalize(); + EXPECT_EQ(histogram_[value_1], + counts_1 / static_cast<double>(counts_1 + counts_2)); + EXPECT_EQ(histogram_[value_2], + counts_2 / static_cast<double>(counts_1 + counts_2)); +} + +TEST_F(TargetHistogramTest, NormalizeEmptyDistribution) { + // Normalizing an empty distribution should result in an empty distribution. + histogram_.Normalize(); + EXPECT_EQ(histogram_.total_counts(), 0); +} + +} // namespace learning +} // namespace media
diff --git a/media/learning/impl/voting_ensemble.cc b/media/learning/impl/voting_ensemble.cc index 667e7399..ef07b1c 100644 --- a/media/learning/impl/voting_ensemble.cc +++ b/media/learning/impl/voting_ensemble.cc
@@ -12,9 +12,9 @@ VotingEnsemble::~VotingEnsemble() = default; -TargetDistribution VotingEnsemble::PredictDistribution( +TargetHistogram VotingEnsemble::PredictDistribution( const FeatureVector& instance) { - TargetDistribution distribution; + TargetHistogram distribution; for (auto iter = models_.begin(); iter != models_.end(); iter++) distribution += (*iter)->PredictDistribution(instance);
diff --git a/media/learning/impl/voting_ensemble.h b/media/learning/impl/voting_ensemble.h index 2b4bf11..7e0cba7 100644 --- a/media/learning/impl/voting_ensemble.h +++ b/media/learning/impl/voting_ensemble.h
@@ -23,8 +23,7 @@ ~VotingEnsemble() override; // Model - TargetDistribution PredictDistribution( - const FeatureVector& instance) override; + TargetHistogram PredictDistribution(const FeatureVector& instance) override; private: std::vector<std::unique_ptr<Model>> models_;
diff --git a/mojo/core/channel_mac.cc b/mojo/core/channel_mac.cc index ea28ae3..0043335 100644 --- a/mojo/core/channel_mac.cc +++ b/mojo/core/channel_mac.cc
@@ -117,6 +117,11 @@ size_t extra_header_size, std::vector<PlatformHandle>* handles, bool* deferred) override { + // TODO(https://crbug.com/946372): Remove when fixed. + static base::debug::CrashKeyString* error_crash_key = + base::debug::AllocateCrashKeyString("channel-mac-handles-error", + base::debug::CrashKeySize::Size64); + // Validate the incoming handles. If validation fails, ensure they are // destroyed. std::vector<PlatformHandle> incoming_handles; @@ -125,12 +130,14 @@ if (extra_header_size < sizeof(Message::MachPortsExtraHeader) + (incoming_handles.size() * sizeof(Message::MachPortsEntry))) { + base::debug::SetCrashKeyString(error_crash_key, "extra_header_size"); return false; } const auto* mach_ports_header = reinterpret_cast<const Message::MachPortsExtraHeader*>(extra_header); if (mach_ports_header->num_ports != incoming_handles.size()) { + base::debug::SetCrashKeyString(error_crash_key, "num_ports mismatch"); return false; } @@ -138,19 +145,29 @@ auto type = static_cast<PlatformHandle::Type>( mach_ports_header->entries[i].mach_entry.type); if (type == PlatformHandle::Type::kNone) { + base::debug::SetCrashKeyString( + error_crash_key, base::StringPrintf("kNone handle #%d", i)); return false; } else if (type == PlatformHandle::Type::kFd && incoming_handles[i].is_mach_send()) { int fd = fileport_makefd(incoming_handles[i].GetMachSendRight().get()); if (fd < 0) { + base::debug::SetCrashKeyString( + error_crash_key, + base::StringPrintf("fileport_makefd %d -%d #%d", fd, errno, i)); return false; } incoming_handles[i] = PlatformHandle(base::ScopedFD(fd)); } else if (type != incoming_handles[i].type()) { + base::debug::SetCrashKeyString( + error_crash_key, + base::StringPrintf("handle mismatch %d != -%d #%d", type, + incoming_handles[i].type(), i)); return false; } } + base::debug::ClearCrashKeyString(error_crash_key); *handles = std::move(incoming_handles); return true; } @@ -251,7 +268,7 @@ MACH_LOG(ERROR, kr) << "mach_msg send handshake"; base::AutoLock lock(write_lock_); - OnWriteErrorLocked(Error::kConnectionFailed, kr); + OnWriteErrorLocked(Error::kConnectionFailed); return; } @@ -388,7 +405,7 @@ fileport_makeport(handle.GetFD().get(), &descriptor->name); if (kr != KERN_SUCCESS) { MACH_LOG(ERROR, kr) << "fileport_makeport"; - OnWriteErrorLocked(Error::kDisconnected, kr); + OnWriteErrorLocked(Error::kDisconnected); return false; } descriptor->disposition = MACH_MSG_TYPE_MOVE_SEND; @@ -397,7 +414,7 @@ default: NOTREACHED() << "Unsupported handle type " << static_cast<int>(handle.type()); - OnWriteErrorLocked(Error::kDisconnected, 0xbad04adl); + OnWriteErrorLocked(Error::kDisconnected); } } @@ -441,7 +458,7 @@ MACH_LOG_IF(ERROR, kr != MACH_SEND_INVALID_DEST, kr) << "mach_msg send"; send_buffer_contains_message_ = false; mach_msg_destroy(header); - OnWriteErrorLocked(Error::kDisconnected, kr); + OnWriteErrorLocked(Error::kDisconnected); } return false; } @@ -623,21 +640,19 @@ size_t ignored; DispatchResult result = TryDispatchMessage(payload, &ignored); if (result != DispatchResult::kOK) { + // TODO(https://crbug.com/946372): Remove when fixed. + static auto* error_crash_key = base::debug::AllocateCrashKeyString( + "channel-mac-try-dispatch", base::debug::CrashKeySize::Size32); + base::debug::SetCrashKeyString(error_crash_key, + base::StringPrintf("%d", result)); + base::debug::DumpWithoutCrashing(); OnError(Error::kReceivedMalformedData); return; } } // Marks the channel as unaccepting of new messages and shuts it down. - void OnWriteErrorLocked(Error error, uint32_t error_code) { - // TODO(https://crbug.com/946372): Remove when fixed. - static base::debug::CrashKeyString* error_crash_key = - base::debug::AllocateCrashKeyString("channel-mac-write-error", - base::debug::CrashKeySize::Size32); - base::debug::SetCrashKeyString(error_crash_key, - base::StringPrintf("0x%x", error_code)); - base::debug::DumpWithoutCrashing(); - + void OnWriteErrorLocked(Error error) { reject_writes_ = true; io_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ChannelMac::OnError, this, error));
diff --git a/mojo/public/cpp/bindings/lib/serialization_util.h b/mojo/public/cpp/bindings/lib/serialization_util.h index a7a99b3..51eb5f23 100644 --- a/mojo/public/cpp/bindings/lib/serialization_util.h +++ b/mojo/public/cpp/bindings/lib/serialization_util.h
@@ -77,62 +77,6 @@ return false; } -template <typename T> -struct HasSetUpContextMethod { - template <typename U> - static char Test(decltype(U::SetUpContext) *); - template <typename U> - static int Test(...); - static const bool value = sizeof(Test<T>(0)) == sizeof(char); - - private: - EnsureTypeIsComplete<T> check_t_; -}; - -template <typename Traits, - bool has_context = HasSetUpContextMethod<Traits>::value> -struct CustomContextHelper; - -template <typename Traits> -struct CustomContextHelper<Traits, true> { - template <typename MaybeConstUserType> - static void* SetUp(MaybeConstUserType& input, SerializationContext* context) { - return Traits::SetUpContext(input); - } - - template <typename MaybeConstUserType> - static void TearDown(MaybeConstUserType& input, void* custom_context) { - Traits::TearDownContext(input, custom_context); - } -}; - -template <typename Traits> -struct CustomContextHelper<Traits, false> { - template <typename MaybeConstUserType> - static void* SetUp(MaybeConstUserType& input, SerializationContext* context) { - return nullptr; - } - - template <typename MaybeConstUserType> - static void TearDown(MaybeConstUserType& input, void* custom_context) { - DCHECK(!custom_context); - } -}; - -template <typename ReturnType, typename ParamType, typename InputUserType> -ReturnType CallWithContext(ReturnType (*f)(ParamType, void*), - InputUserType&& input, - void* context) { - return f(std::forward<InputUserType>(input), context); -} - -template <typename ReturnType, typename ParamType, typename InputUserType> -ReturnType CallWithContext(ReturnType (*f)(ParamType), - InputUserType&& input, - void* context) { - return f(std::forward<InputUserType>(input)); -} - template <typename T, typename MaybeConstUserType> struct HasGetBeginMethod { template <typename U>
diff --git a/mojo/public/cpp/bindings/lib/string_serialization.h b/mojo/public/cpp/bindings/lib/string_serialization.h index 1fe6b87..d11a0c7 100644 --- a/mojo/public/cpp/bindings/lib/string_serialization.h +++ b/mojo/public/cpp/bindings/lib/string_serialization.h
@@ -29,12 +29,9 @@ if (CallIsNullIfExists<Traits>(input)) return; - void* custom_context = CustomContextHelper<Traits>::SetUp(input, context); - const size_t size = CallWithContext(Traits::GetSize, input, custom_context); - writer->Allocate(size, buffer); - memcpy((*writer)->storage(), - CallWithContext(Traits::GetData, input, custom_context), size); - CustomContextHelper<Traits>::TearDown(input, custom_context); + auto r = Traits::GetUTF8(input); + writer->Allocate(r.size(), buffer); + memcpy((*writer)->storage(), r.data(), r.size()); } static bool Deserialize(String_Data* input,
diff --git a/mojo/public/cpp/bindings/lib/string_traits_wtf.cc b/mojo/public/cpp/bindings/lib/string_traits_wtf.cc index 71b758c..540a154 100644 --- a/mojo/public/cpp/bindings/lib/string_traits_wtf.cc +++ b/mojo/public/cpp/bindings/lib/string_traits_wtf.cc
@@ -4,43 +4,9 @@ #include "mojo/public/cpp/bindings/string_traits_wtf.h" -#include <string.h> - -#include "base/logging.h" -#include "mojo/public/cpp/bindings/lib/array_internal.h" #include "mojo/public/cpp/bindings/string_data_view.h" -#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h" namespace mojo { -namespace { - -struct UTF8AdaptorInfo { - explicit UTF8AdaptorInfo(const WTF::String& input) : utf8_adaptor(input) { -#if DCHECK_IS_ON() - original_size_in_bytes = input.CharactersSizeInBytes(); -#endif - } - - ~UTF8AdaptorInfo() {} - - WTF::StringUTF8Adaptor utf8_adaptor; - -#if DCHECK_IS_ON() - // For sanity check only. - size_t original_size_in_bytes; -#endif -}; - -UTF8AdaptorInfo* ToAdaptor(const WTF::String& input, void* context) { - UTF8AdaptorInfo* adaptor = static_cast<UTF8AdaptorInfo*>(context); - -#if DCHECK_IS_ON() - DCHECK_EQ(adaptor->original_size_in_bytes, input.CharactersSizeInBytes()); -#endif - return adaptor; -} - -} // namespace // static void StringTraits<WTF::String>::SetToNull(WTF::String* output) { @@ -52,26 +18,9 @@ } // static -void* StringTraits<WTF::String>::SetUpContext(const WTF::String& input) { - return new UTF8AdaptorInfo(input); -} - -// static -void StringTraits<WTF::String>::TearDownContext(const WTF::String& input, - void* context) { - delete ToAdaptor(input, context); -} - -// static -size_t StringTraits<WTF::String>::GetSize(const WTF::String& input, - void* context) { - return ToAdaptor(input, context)->utf8_adaptor.length(); -} - -// static -const char* StringTraits<WTF::String>::GetData(const WTF::String& input, - void* context) { - return ToAdaptor(input, context)->utf8_adaptor.Data(); +WTF::StringUTF8Adaptor StringTraits<WTF::String>::GetUTF8( + const WTF::String& input) { + return WTF::StringUTF8Adaptor(input); } // static
diff --git a/mojo/public/cpp/bindings/string_traits.h b/mojo/public/cpp/bindings/string_traits.h index 165c9fa..bd25647 100644 --- a/mojo/public/cpp/bindings/string_traits.h +++ b/mojo/public/cpp/bindings/string_traits.h
@@ -12,8 +12,7 @@ // This must be specialized for any type |T| to be serialized/deserialized as // a mojom string. // -// Imagine you want to specialize it for CustomString, usually you need to -// implement: +// An example specialization for CustomString: // // template <T> // struct StringTraits<CustomString> { @@ -21,31 +20,14 @@ // static bool IsNull(const CustomString& input); // static void SetToNull(CustomString* output); // -// static size_t GetSize(const CustomString& input); -// static const char* GetData(const CustomString& input); +// // This doesn't need to be a base::StringPiece; it simply needs to be a +// // type that exposes a data() method that returns a pointer to the UTF-8 +// // bytes and a size() method that returns the length of the UTF-8 bytes. +// static std::span<char> GetUTF8(const CustomString& input); // // // The caller guarantees that |!input.is_null()|. // static bool Read(StringDataView input, CustomString* output); // }; -// -// In some cases, you may need to do conversion before you can return the size -// and data as 8-bit characters for serialization. (For example, CustomString is -// UTF-16 string). In that case, you can add two optional methods: -// -// static void* SetUpContext(const CustomString& input); -// static void TearDownContext(const CustomString& input, void* context); -// -// And then you append a second parameter, void* context, to GetSize() and -// GetData(): -// -// static size_t GetSize(const CustomString& input, void* context); -// static const char* GetData(const CustomString& input, void* context); -// -// If a CustomString instance is not null, the serialization code will call -// SetUpContext() at the beginning, and pass the resulting context pointer to -// GetSize()/GetData(). After serialization is done, it calls TearDownContext() -// so that you can do any necessary cleanup. -// template <typename T> struct StringTraits { static_assert(internal::AlwaysFalse<T>::value,
diff --git a/mojo/public/cpp/bindings/string_traits_stl.h b/mojo/public/cpp/bindings/string_traits_stl.h index f6cc8ad09..cb3c5fb 100644 --- a/mojo/public/cpp/bindings/string_traits_stl.h +++ b/mojo/public/cpp/bindings/string_traits_stl.h
@@ -23,9 +23,7 @@ output->clear(); } - static size_t GetSize(const std::string& input) { return input.size(); } - - static const char* GetData(const std::string& input) { return input.data(); } + static const std::string& GetUTF8(const std::string& input) { return input; } static bool Read(StringDataView input, std::string* output) { output->assign(input.storage(), input.size());
diff --git a/mojo/public/cpp/bindings/string_traits_string_piece.h b/mojo/public/cpp/bindings/string_traits_string_piece.h index af6be89..7855379 100644 --- a/mojo/public/cpp/bindings/string_traits_string_piece.h +++ b/mojo/public/cpp/bindings/string_traits_string_piece.h
@@ -12,7 +12,7 @@ template <> struct StringTraits<base::StringPiece> { - static bool IsNull(const base::StringPiece& input) { + static bool IsNull(base::StringPiece input) { // base::StringPiece is always converted to non-null mojom string. We could // have let StringPiece containing a null data pointer map to null mojom // string, but StringPiece::empty() returns true in this case. It seems @@ -26,11 +26,7 @@ output->set(nullptr, 0); } - static size_t GetSize(const base::StringPiece& input) { return input.size(); } - - static const char* GetData(const base::StringPiece& input) { - return input.data(); - } + static base::StringPiece GetUTF8(base::StringPiece input) { return input; } static bool Read(StringDataView input, base::StringPiece* output) { output->set(input.storage(), input.size());
diff --git a/mojo/public/cpp/bindings/string_traits_wtf.h b/mojo/public/cpp/bindings/string_traits_wtf.h index 51601d1a..662fff5 100644 --- a/mojo/public/cpp/bindings/string_traits_wtf.h +++ b/mojo/public/cpp/bindings/string_traits_wtf.h
@@ -7,6 +7,7 @@ #include "mojo/public/cpp/bindings/lib/bindings_internal.h" #include "mojo/public/cpp/bindings/string_traits.h" +#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace mojo { @@ -16,12 +17,7 @@ static bool IsNull(const WTF::String& input) { return input.IsNull(); } static void SetToNull(WTF::String* output); - static void* SetUpContext(const WTF::String& input); - static void TearDownContext(const WTF::String& input, void* context); - - static size_t GetSize(const WTF::String& input, void* context); - - static const char* GetData(const WTF::String& input, void* context); + static WTF::StringUTF8Adaptor GetUTF8(const WTF::String& input); static bool Read(StringDataView input, WTF::String* output); };
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl index 5571e84..5f11278 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/struct_serialization_declaration.tmpl
@@ -17,12 +17,10 @@ SerializationContext* context) { if (CallIsNullIfExists<Traits>(input)) return; - void* custom_context = CustomContextHelper<Traits>::SetUp(input, context); {{struct_macros.serialize( struct, struct.name ~ " struct", - "CallWithContext(Traits::%s, input, custom_context)", "(*output)", + "Traits::%s(input)", "(*output)", "buffer", "context", True)|indent(2)}} - CustomContextHelper<Traits>::TearDown(input, custom_context); } static bool Deserialize({{data_type}}* input,
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl index 4e39774..3e98ede 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_declaration.tmpl
@@ -18,8 +18,6 @@ writer->data()->set_null(); return; } - void* custom_context = CustomContextHelper<Traits>::SetUp(input, context); - if (!inlined) writer->Allocate(buffer); @@ -28,16 +26,15 @@ // TODO(azani): Handle unknown and objects. // Set the not-null flag. result->size = kUnionDataSize; - result->tag = CallWithContext(Traits::GetTag, input, custom_context); + result->tag = Traits::GetTag(input); switch (result->tag) { {%- for field in union.fields %} {%- set name = field.name %} {%- set kind = field.kind %} {%- set serializer_type = kind|unmapped_type_for_serializer %} case {{data_view}}::Tag::{{field.name|upper}}: { - decltype(CallWithContext(Traits::{{name}}, input, custom_context)) - in_{{name}} = CallWithContext(Traits::{{name}}, input, - custom_context); + decltype(Traits::{{name}}(input)) + in_{{name}} = Traits::{{name}}(input); {%- if kind|is_object_kind %} typename decltype(result->data.f_{{name}})::BaseType::BufferWriter value_writer; @@ -88,8 +85,6 @@ } {%- endfor %} } - - CustomContextHelper<Traits>::TearDown(input, custom_context); } static bool Deserialize({{data_type}}* input,
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc index f021464..1fca778 100644 --- a/net/base/network_change_notifier.cc +++ b/net/base/network_change_notifier.cc
@@ -207,7 +207,7 @@ CHECK(false); return NULL; #elif defined(OS_CHROMEOS) - return new NetworkChangeNotifierPosix(CONNECTION_UNKNOWN, SUBTYPE_UNKNOWN); + return new NetworkChangeNotifierPosix(CONNECTION_NONE, SUBTYPE_NONE); #elif defined(OS_LINUX) return new NetworkChangeNotifierLinux(std::unordered_set<std::string>()); #elif defined(OS_MACOSX)
diff --git a/net/base/network_change_notifier_posix.cc b/net/base/network_change_notifier_posix.cc index e8dc5b1..68d1f090b 100644 --- a/net/base/network_change_notifier_posix.cc +++ b/net/base/network_change_notifier_posix.cc
@@ -24,9 +24,8 @@ : public net::internal::DnsConfigServicePosix { public: DnsConfigService() { - // After construction it lives on - // NetworkChangeNotifierPosix::dns_config_service_runner_. - DETACH_FROM_SEQUENCE(sequence_checker_); + WatchConfig(base::BindRepeating(&NetworkChangeNotifier::SetDnsConfig)); + OnNetworkChange(); } ~DnsConfigService() override = default; @@ -51,7 +50,7 @@ dns_config_service_runner_( base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()})), dns_config_service_( - new DnsConfigService(), + nullptr, // Ensure DnsConfigService lives on |dns_config_service_runner_| // to prevent races where NetworkChangeNotifierPosix outlives // ScopedTaskEnvironment. https://crbug.com/938126 @@ -62,15 +61,19 @@ initial_connection_subtype)) { dns_config_service_runner_->PostTask( FROM_HERE, - base::BindOnce( - &NetworkChangeNotifierPosix::DnsConfigService::WatchConfig, - base::Unretained(dns_config_service_.get()), - base::BindRepeating(&NetworkChangeNotifier::SetDnsConfig))); - OnDNSChanged(); + base::BindOnce(&NetworkChangeNotifierPosix::CreateDnsConfigService, + // The Unretained pointer is safe here because |this| owns + // |dns_config_service_runner_|. + base::Unretained(this))); } NetworkChangeNotifierPosix::~NetworkChangeNotifierPosix() = default; +void NetworkChangeNotifierPosix::CreateDnsConfigService() { + DCHECK(dns_config_service_runner_->RunsTasksInCurrentSequence()); + dns_config_service_.reset(new DnsConfigService()); +} + void NetworkChangeNotifierPosix::OnDNSChanged() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); dns_config_service_runner_->PostTask(
diff --git a/net/base/network_change_notifier_posix.h b/net/base/network_change_notifier_posix.h index eefd15f..1fdd88c2 100644 --- a/net/base/network_change_notifier_posix.h +++ b/net/base/network_change_notifier_posix.h
@@ -59,11 +59,7 @@ class DnsConfigService; - // |dns_config_service_| will live on this runner. - scoped_refptr<base::SequencedTaskRunner> dns_config_service_runner_; - // DnsConfigService that lives on |dns_config_service_runner_|. - std::unique_ptr<DnsConfigService, base::OnTaskRunnerDeleter> - dns_config_service_; + void CreateDnsConfigService(); // Calculates parameters used for network change notifier online/offline // signals. @@ -72,6 +68,12 @@ THREAD_CHECKER(thread_checker_); + // |dns_config_service_| will live on this runner. + scoped_refptr<base::SequencedTaskRunner> dns_config_service_runner_; + // DnsConfigService that lives on |dns_config_service_runner_|. + std::unique_ptr<DnsConfigService, base::OnTaskRunnerDeleter> + dns_config_service_; + mutable base::Lock lock_; NetworkChangeNotifier::ConnectionType connection_type_; // Guarded by |lock_|.
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index 11af7a65..d93a76a 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -286,18 +286,24 @@ // Now we force HTTPS for subtrees of google.com. { "name": "accounts.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "admin.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, + { "name": "apis.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "appengine.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, + { "name": "calendar.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "checkout.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "chrome.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "classroom.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "cloud.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, + { "name": "code.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "contributor.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, + { "name": "dl.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "docs.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "domains.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, + { "name": "drive.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "encrypted.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "fi.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "glass.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "goto.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, + { "name": "groups.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "hangouts.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "history.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "hostedtalkgadget.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, @@ -324,21 +330,17 @@ { "name": "dns.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, // Other Google-related domains that must use HTTPS. - { "name": "apis.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "build.chromium.org", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "bugs.chromium.org", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "cdn.ampproject.org", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "chrome.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "chrome-devtools-frontend.appspot.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "chromiumcodereview.appspot.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, - { "name": "code.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "codereview.appspot.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "codereview.chromium.org", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "crbug.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "crosbug.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "crrev.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, - { "name": "dl.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, - { "name": "drive.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "firebaseio.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "g.co", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "g4w.co", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, @@ -348,7 +350,6 @@ { "name": "googlemail.com", "policy": "google", "mode": "force-https", "pins": "google" }, { "name": "googleplex.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "googlesource.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, - { "name": "groups.google.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "gvt2.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "gvt3.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "developer.android.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, @@ -379,11 +380,6 @@ { "name": "w-spotlight.appspot.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, { "name": "xbrlsuccess.appspot.com", "policy": "google", "mode": "force-https", "include_subdomains": true, "pins": "google" }, - // chart.apis.google.com is *not* HSTS because the certificate doesn't match - // and there are lots of links out there that still use the name. The correct - // hostname for this is chart.googleapis.com. - { "name": "chart.apis.google.com", "policy": "google", "include_subdomains": true, "pins": "google" }, - // Other Google-related domains that must use an acceptable certificate // iff using SSL. { "name": "2mdn.net", "policy": "google", "include_subdomains": true, "pins": "google" },
diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc index 0ce0c96..3c5ca3f1e 100644 --- a/net/http/transport_security_state_unittest.cc +++ b/net/http/transport_security_state_unittest.cc
@@ -2619,7 +2619,6 @@ EXPECT_TRUE(StaticShouldRedirect("plus.google.com")); EXPECT_TRUE(StaticShouldRedirect("groups.google.com")); EXPECT_TRUE(StaticShouldRedirect("apis.google.com")); - EXPECT_FALSE(StaticShouldRedirect("chart.apis.google.com")); EXPECT_TRUE(StaticShouldRedirect("ssl.google-analytics.com")); EXPECT_TRUE(StaticShouldRedirect("google")); EXPECT_TRUE(StaticShouldRedirect("foo.google"));
diff --git a/ppapi/PRESUBMIT.py b/ppapi/PRESUBMIT.py index ff33c21..b48b01b 100644 --- a/ppapi/PRESUBMIT.py +++ b/ppapi/PRESUBMIT.py
@@ -167,7 +167,8 @@ 'ppapi/thunk/interfaces_ppb_private_no_permissions.h', 'ppapi/thunk/interfaces_ppb_public_dev_channel.h', 'ppapi/thunk/interfaces_ppb_public_dev.h', - 'ppapi/thunk/interfaces_ppb_public_stable.h') + 'ppapi/thunk/interfaces_ppb_public_stable.h', + 'ppapi/thunk/interfaces_ppb_public_socket.h') HISTOGRAM_XML_FILE = 'tools/metrics/histograms/enums.xml' interface_changes = [] has_histogram_xml_change = False
diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc index e8702cc..cd51d9f 100644 --- a/ppapi/proxy/interface_list.cc +++ b/ppapi/proxy/interface_list.cc
@@ -180,6 +180,7 @@ INTERFACE_THUNK_NAME(iface_struct)(), \ current_required_permission); + // clang-format off { Permission current_required_permission = PERMISSION_NONE; #include "ppapi/thunk/interfaces_ppb_private_no_permissions.h" @@ -207,9 +208,14 @@ Permission current_required_permission = PERMISSION_DEV_CHANNEL; #include "ppapi/thunk/interfaces_ppb_public_dev_channel.h" } + { + Permission current_required_permission = PERMISSION_SOCKET; + #include "ppapi/thunk/interfaces_ppb_public_socket.h" + } + // clang-format on - #undef PROXIED_API - #undef PROXIED_IFACE +#undef PROXIED_API +#undef PROXIED_IFACE // Manually add some special proxies. Some of these don't have interfaces // that they support, so aren't covered by the macros above, but have proxies
diff --git a/ppapi/shared_impl/ppapi_permissions.h b/ppapi/shared_impl/ppapi_permissions.h index 5d3ef58..da55c81 100644 --- a/ppapi/shared_impl/ppapi_permissions.h +++ b/ppapi/shared_impl/ppapi_permissions.h
@@ -40,19 +40,22 @@ // PDF-related interfaces. PERMISSION_PDF = 1 << 6, + // Socket APIs. Formerly part of public APIs. + PERMISSION_SOCKET = 1 << 7, + // NOTE: If you add stuff be sure to update PERMISSION_ALL_BITS. // Meta permission for for initializing plugins with permissions that have - // historically been part of public APIs but will be covered by finer-grained - // permissions in the future. - PERMISSION_DEFAULT = PERMISSION_NONE, + // historically been part of public APIs but are now covered by finer-grained + // permissions. + PERMISSION_DEFAULT = PERMISSION_SOCKET, // Meta permission for initializing plugins registered on the command line // that get all permissions. PERMISSION_ALL_BITS = PERMISSION_DEV | PERMISSION_PRIVATE | PERMISSION_BYPASS_USER_GESTURE | PERMISSION_TESTING | PERMISSION_FLASH | PERMISSION_DEV_CHANNEL | - PERMISSION_PDF + PERMISSION_PDF | PERMISSION_SOCKET, }; class PPAPI_SHARED_EXPORT PpapiPermissions {
diff --git a/ppapi/thunk/BUILD.gn b/ppapi/thunk/BUILD.gn index 8be4fa9d..79825273 100644 --- a/ppapi/thunk/BUILD.gn +++ b/ppapi/thunk/BUILD.gn
@@ -19,6 +19,7 @@ "interfaces_ppb_private_no_permissions.h", "interfaces_ppb_public_dev.h", "interfaces_ppb_public_dev_channel.h", + "interfaces_ppb_public_socket.h", "interfaces_ppb_public_stable.h", "interfaces_preamble.h", "ppapi_thunk_export.h",
diff --git a/ppapi/thunk/interfaces_ppb_public_socket.h b/ppapi/thunk/interfaces_ppb_public_socket.h new file mode 100644 index 0000000..f79f7e7 --- /dev/null +++ b/ppapi/thunk/interfaces_ppb_public_socket.h
@@ -0,0 +1,18 @@ +// Copyright (c) 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. + +// no-include-guard-because-multiply-included +// NOLINT(build/header_guard) + +#include "ppapi/thunk/interfaces_preamble.h" + +// See interfaces_ppp_public_stable.h for documentation on these macros. +PROXIED_IFACE(PPB_TCPSOCKET_INTERFACE_1_0, PPB_TCPSocket_1_0) +PROXIED_IFACE(PPB_TCPSOCKET_INTERFACE_1_1, PPB_TCPSocket_1_1) +PROXIED_IFACE(PPB_TCPSOCKET_INTERFACE_1_2, PPB_TCPSocket_1_2) +PROXIED_IFACE(PPB_UDPSOCKET_INTERFACE_1_0, PPB_UDPSocket_1_0) +PROXIED_IFACE(PPB_UDPSOCKET_INTERFACE_1_1, PPB_UDPSocket_1_1) +PROXIED_IFACE(PPB_UDPSOCKET_INTERFACE_1_2, PPB_UDPSocket_1_2) + +#include "ppapi/thunk/interfaces_postamble.h"
diff --git a/ppapi/thunk/interfaces_ppb_public_stable.h b/ppapi/thunk/interfaces_ppb_public_stable.h index 83b3cfa..4d66348 100644 --- a/ppapi/thunk/interfaces_ppb_public_stable.h +++ b/ppapi/thunk/interfaces_ppb_public_stable.h
@@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// no-include-guard-because-multiply-included +// NOLINT(build/header_guard) + #include "ppapi/thunk/interfaces_preamble.h" // This file contains lists of interfaces. It's intended to be included by @@ -86,14 +89,8 @@ PROXIED_IFACE(PPB_NETWORKLIST_INTERFACE_1_0, PPB_NetworkList_1_0) PROXIED_IFACE(PPB_NETWORKMONITOR_INTERFACE_1_0, PPB_NetworkMonitor_1_0) PROXIED_IFACE(PPB_NETWORKPROXY_INTERFACE_1_0, PPB_NetworkProxy_1_0) -PROXIED_IFACE(PPB_TCPSOCKET_INTERFACE_1_0, PPB_TCPSocket_1_0) -PROXIED_IFACE(PPB_TCPSOCKET_INTERFACE_1_1, PPB_TCPSocket_1_1) -PROXIED_IFACE(PPB_TCPSOCKET_INTERFACE_1_2, PPB_TCPSocket_1_2) PROXIED_IFACE(PPB_TEXTINPUTCONTROLLER_INTERFACE_1_0, PPB_TextInputController_1_0) -PROXIED_IFACE(PPB_UDPSOCKET_INTERFACE_1_0, PPB_UDPSocket_1_0) -PROXIED_IFACE(PPB_UDPSOCKET_INTERFACE_1_1, PPB_UDPSocket_1_1) -PROXIED_IFACE(PPB_UDPSOCKET_INTERFACE_1_2, PPB_UDPSocket_1_2) PROXIED_IFACE(PPB_URLLOADER_INTERFACE_1_0, PPB_URLLoader_1_0) PROXIED_IFACE(PPB_URLREQUESTINFO_INTERFACE_1_0, PPB_URLRequestInfo_1_0) PROXIED_IFACE(PPB_URLRESPONSEINFO_INTERFACE_1_0, PPB_URLResponseInfo_1_0)
diff --git a/ppapi/thunk/thunk.h b/ppapi/thunk/thunk.h index 54b3ded..99a24c6 100644 --- a/ppapi/thunk/thunk.h +++ b/ppapi/thunk/thunk.h
@@ -24,8 +24,8 @@ #include "ppapi/thunk/interfaces_ppb_private_pdf.h" #include "ppapi/thunk/interfaces_ppb_public_dev.h" #include "ppapi/thunk/interfaces_ppb_public_dev_channel.h" +#include "ppapi/thunk/interfaces_ppb_public_socket.h" #include "ppapi/thunk/interfaces_ppb_public_stable.h" - #undef PROXIED_IFACE namespace ppapi {
diff --git a/services/service_manager/sandbox/features.cc b/services/service_manager/sandbox/features.cc index 91f9952b..0674345 100644 --- a/services/service_manager/sandbox/features.cc +++ b/services/service_manager/sandbox/features.cc
@@ -26,7 +26,7 @@ "WinSboxDisableExtensionPoint", base::FEATURE_ENABLED_BY_DEFAULT}; // Controls whether the isolated XR service is sandboxed. -const base::Feature kXRSandbox{"XRSandbox", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kXRSandbox{"XRSandbox", base::FEATURE_ENABLED_BY_DEFAULT}; #endif // defined(OS_WIN) } // namespace features
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn index 66c1014..9f152855 100644 --- a/third_party/blink/public/common/BUILD.gn +++ b/third_party/blink/public/common/BUILD.gn
@@ -91,6 +91,7 @@ "origin_trials/trial_token.h", "origin_trials/trial_token_validator.h", "page/launching_process_state.h", + "prerender/prerender_rel_type.h", "privacy_preferences.h", "screen_orientation/web_screen_orientation_lock_type.h", "screen_orientation/web_screen_orientation_type.h",
diff --git a/third_party/blink/public/common/prerender/OWNERS b/third_party/blink/public/common/prerender/OWNERS new file mode 100644 index 0000000..c71af0e --- /dev/null +++ b/third_party/blink/public/common/prerender/OWNERS
@@ -0,0 +1,3 @@ +file://chrome/browser/prerender/OWNERS + +# COMPONENT: Internals>Preload
diff --git a/third_party/blink/public/common/prerender/prerender_rel_type.h b/third_party/blink/public/common/prerender/prerender_rel_type.h new file mode 100644 index 0000000..e0450ac --- /dev/null +++ b/third_party/blink/public/common/prerender/prerender_rel_type.h
@@ -0,0 +1,19 @@ +// 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_PUBLIC_COMMON_PRERENDER_PRERENDER_REL_TYPE_H_ +#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRERENDER_PRERENDER_REL_TYPE_H_ + +namespace blink { + +// WebPrerenderRelType is a bitfield since multiple rel attributes can be set on +// the same prerender. +enum WebPrerenderRelType { + kPrerenderRelTypePrerender = 0x1, + kPrerenderRelTypeNext = 0x2, +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRERENDER_PRERENDER_REL_TYPE_H_
diff --git a/third_party/blink/public/platform/DEPS b/third_party/blink/public/platform/DEPS index 78346615..cafa3e7 100644 --- a/third_party/blink/public/platform/DEPS +++ b/third_party/blink/public/platform/DEPS
@@ -34,6 +34,7 @@ # Enforce to use mojom-shared.h in blink/public so that it can compile # inside and outside Blink. + "+media/mojo/interfaces/display_media_information.mojom-shared.h", "+services/network/public/mojom/cors.mojom-shared.h", "+services/network/public/mojom/fetch_api.mojom-shared.h", "+services/network/public/mojom/request_context_frame_type.mojom-shared.h",
diff --git a/third_party/blink/public/platform/web_media_stream_track.h b/third_party/blink/public/platform/web_media_stream_track.h index 5fa8699..9234b84 100644 --- a/third_party/blink/public/platform/web_media_stream_track.h +++ b/third_party/blink/public/platform/web_media_stream_track.h
@@ -28,6 +28,7 @@ #include <memory> #include "base/optional.h" +#include "media/mojo/interfaces/display_media_information.mojom-shared.h" #include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/platform/web_private_ptr.h" #include "third_party/blink/public/platform/web_string.h" @@ -45,13 +46,6 @@ class WebMediaStreamTrack { public: enum class FacingMode { kNone, kUser, kEnvironment, kLeft, kRight }; - enum class DisplayCaptureSurfaceType { - kMonitor, - kWindow, - kApplication, - kBrowser - }; - enum class CursorCaptureType { kNever, kAlways, kMotion }; BLINK_PLATFORM_EXPORT static const char kResizeModeNone[]; BLINK_PLATFORM_EXPORT static const char kResizeModeRescale[]; @@ -92,9 +86,9 @@ WebString video_kind; // Screen Capture extensions - base::Optional<DisplayCaptureSurfaceType> display_surface; + base::Optional<media::mojom::DisplayCaptureSurfaceType> display_surface; base::Optional<bool> logical_surface; - base::Optional<CursorCaptureType> cursor; + base::Optional<media::mojom::CursorCaptureType> cursor; }; enum class ContentHintType {
diff --git a/third_party/blink/public/platform/web_prerender.h b/third_party/blink/public/platform/web_prerender.h index 8f7ca35..4a3317ce 100644 --- a/third_party/blink/public/platform/web_prerender.h +++ b/third_party/blink/public/platform/web_prerender.h
@@ -41,13 +41,6 @@ class Prerender; -// WebPrerenderRelType is a bitfield since multiple rel attributes can be set on -// the same prerender. -enum WebPrerenderRelType { - kPrerenderRelTypePrerender = 0x1, - kPrerenderRelTypeNext = 0x2, -}; - class WebPrerender { public: class ExtraData {
diff --git a/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util_video_device.h b/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util_video_device.h index e4b6005c..803fa9f 100644 --- a/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util_video_device.h +++ b/third_party/blink/public/web/modules/mediastream/media_stream_constraints_util_video_device.h
@@ -28,12 +28,6 @@ BLINK_EXPORT WebMediaStreamTrack::FacingMode ToWebFacingMode( media::VideoFacingMode video_facing); -BLINK_EXPORT WebMediaStreamTrack::DisplayCaptureSurfaceType ToWebDisplaySurface( - media::mojom::DisplayCaptureSurfaceType display_surface); - -BLINK_EXPORT WebMediaStreamTrack::CursorCaptureType ToWebCursorCaptureType( - media::mojom::CursorCaptureType cursor); - // This is a temporary struct to bridge blink and content mojo types. // TODO(crbug.com/704136): Replace references to this type with the blink mojo // type once all dependent types are migrated to Blink.
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc index c890fb0..04fc3a09 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc
@@ -195,8 +195,8 @@ // TODO(jbroman): Ideally this method would take a WTF::StringView, but the // StringUTF8Adaptor trick doesn't yet work with StringView. StringUTF8Adaptor utf8(string); - WriteUint32(utf8.length()); - WriteRawBytes(utf8.Data(), utf8.length()); + WriteUint32(utf8.size()); + WriteRawBytes(utf8.data(), utf8.size()); } bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable,
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc index fe2cd08..0ae9ccd3 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -192,8 +192,7 @@ acquire_resolver_ = MakeGarbageCollected<ScriptPromiseResolver>(script_state); if (auto* layout_object = element_->GetLayoutObject()) { - layout_object->SetNeedsLayout( - layout_invalidation_reason::kDisplayLockCommitting); + layout_object->SetNeedsLayout(layout_invalidation_reason::kDisplayLock); } MarkPaintLayerNeedsRepaint(); ScheduleAnimation(); @@ -540,8 +539,7 @@ // for just the box itself. Note that we use the non-display locked version to // ensure all the hooks are property invoked. ToLayoutBox(layout_object)->SetFrameRect(pending_frame_rect_); - layout_object->SetNeedsLayout( - layout_invalidation_reason::kDisplayLockCommitting); + layout_object->SetNeedsLayout(layout_invalidation_reason::kDisplayLock); } void DisplayLockContext::StartUpdateIfNeeded() { @@ -781,7 +779,7 @@ // the parent so that it's up to date. This property is updated during // layout. if (auto* parent = element_->GetLayoutObject()->Parent()) { - parent->SetNeedsLayout(layout_invalidation_reason::kDisplayLockCommitting); + parent->SetNeedsLayout(layout_invalidation_reason::kDisplayLock); } }
diff --git a/third_party/blink/renderer/core/dom/OWNERS b/third_party/blink/renderer/core/dom/OWNERS index 9ba5f94..1828548 100644 --- a/third_party/blink/renderer/core/dom/OWNERS +++ b/third_party/blink/renderer/core/dom/OWNERS
@@ -1,5 +1,4 @@ hayato@chromium.org -tkent@chromium.org per-file *_struct_traits*.*=set noparent per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/renderer/core/exported/prerendering_test.cc b/third_party/blink/renderer/core/exported/prerendering_test.cc index 59aada9..1c970df 100644 --- a/third_party/blink/renderer/core/exported/prerendering_test.cc +++ b/third_party/blink/renderer/core/exported/prerendering_test.cc
@@ -34,6 +34,7 @@ #include "base/memory/ptr_util.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/prerender/prerender_rel_type.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_cache.h" #include "third_party/blink/public/platform/web_prerender.h"
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 f54ff82..ca2ee4f 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -11595,16 +11595,17 @@ frame->EnsureTextFinder().SelectNearestFindMatch(result_rect.Center(), nullptr); - VisualViewport& visual_viewport = local_frame->GetPage()->GetVisualViewport(); - EXPECT_TRUE(visual_viewport.VisibleRectInDocument().Contains(box1_rect)); - + EXPECT_TRUE(frame_view->GetScrollableArea()->VisibleContentRect().Contains( + box1_rect)); result_rect = static_cast<FloatRect>(web_match_rects[1]); frame->EnsureTextFinder().SelectNearestFindMatch(result_rect.Center(), nullptr); - EXPECT_TRUE(visual_viewport.VisibleRectInDocument().Contains(box2_rect)) + EXPECT_TRUE( + frame_view->GetScrollableArea()->VisibleContentRect().Contains(box2_rect)) << "Box [" << box2_rect.ToString() << "] is not visible in viewport [" - << visual_viewport.VisibleRectInDocument().ToString() << "]"; + << frame_view->GetScrollableArea()->VisibleContentRect().ToString() + << "]"; } // Test bubbling a document (End key) scroll from an inner iframe. This test @@ -11710,13 +11711,13 @@ auto* frame = To<LocalFrame>(WebView().GetPage()->MainFrame()); LocalFrameView* frame_view = frame->View(); - VisualViewport& visual_viewport = frame->GetPage()->GetVisualViewport(); - FloatRect inputRect(200, 600, 100, 20); + IntRect inputRect(200, 600, 100, 20); frame_view->GetScrollableArea()->SetScrollOffset(ScrollOffset(0, 0), kProgrammaticScroll); - ASSERT_EQ(FloatPoint(), visual_viewport.VisibleRectInDocument().Location()); + ASSERT_EQ(FloatPoint(), + frame_view->GetScrollableArea()->VisibleContentRect().Location()); WebView() .MainFrameImpl() @@ -11730,7 +11731,8 @@ WebView().FakePageScaleAnimationTargetPositionForTesting())), kProgrammaticScroll); - EXPECT_TRUE(visual_viewport.VisibleRectInDocument().Contains(inputRect)); + EXPECT_TRUE(frame_view->GetScrollableArea()->VisibleContentRect().Contains( + inputRect)); // Reset the testing getters. WebView().EnableFakePageScaleAnimationForTesting(true); @@ -11748,7 +11750,8 @@ // Now resize the visual viewport so that the input box is no longer in view // (e.g. a keyboard is overlayed). WebView().MainFrameWidget()->ResizeVisualViewport(IntSize(200, 100)); - ASSERT_FALSE(visual_viewport.VisibleRectInDocument().Contains(inputRect)); + ASSERT_FALSE(frame_view->GetScrollableArea()->VisibleContentRect().Contains( + inputRect)); WebView() .MainFrameImpl() @@ -11759,7 +11762,8 @@ WebView().FakePageScaleAnimationTargetPositionForTesting())), kProgrammaticScroll); - EXPECT_TRUE(visual_viewport.VisibleRectInDocument().Contains(inputRect)); + EXPECT_TRUE(frame_view->GetScrollableArea()->VisibleContentRect().Contains( + inputRect)); EXPECT_EQ(1, WebView().FakePageScaleAnimationPageScaleForTesting()); } @@ -11823,11 +11827,13 @@ rs_controller.RootScrollerArea()->SetScrollOffset(ScrollOffset(0, 300), kProgrammaticScroll); - FloatRect inputRect(200, 700, 100, 20); + LocalFrameView* frame_view = frame->View(); + IntRect inputRect(200, 700, 100, 20); ASSERT_EQ(1, visual_viewport.Scale()); ASSERT_EQ(FloatPoint(0, 300), - visual_viewport.VisibleRectInDocument().Location()); - ASSERT_FALSE(visual_viewport.VisibleRectInDocument().Contains(inputRect)); + frame_view->GetScrollableArea()->VisibleContentRect().Location()); + ASSERT_FALSE(frame_view->GetScrollableArea()->VisibleContentRect().Contains( + inputRect)); WebView() .MainFrameImpl() @@ -11842,7 +11848,8 @@ rs_controller.RootScrollerArea()->SetScrollOffset(target_offset, kProgrammaticScroll); - EXPECT_TRUE(visual_viewport.VisibleRectInDocument().Contains(inputRect)); + EXPECT_TRUE(frame_view->GetScrollableArea()->VisibleContentRect().Contains( + inputRect)); } TEST_F(WebFrameSimTest, ScrollFocusedIntoViewClipped) { @@ -11905,7 +11912,8 @@ LocalFrameView* frame_view = frame->View(); VisualViewport& visual_viewport = frame->GetPage()->GetVisualViewport(); - ASSERT_EQ(FloatPoint(), visual_viewport.VisibleRectInDocument().Location()); + ASSERT_EQ(FloatPoint(), + frame_view->GetScrollableArea()->VisibleContentRect().Location()); // Simulate the keyboard being shown and resizing the widget. Cause a scroll // into view after. @@ -11982,7 +11990,7 @@ auto* frame = To<LocalFrame>(WebView().GetPage()->MainFrame()); LocalFrameView* frame_view = frame->View(); VisualViewport& visual_viewport = frame->GetPage()->GetVisualViewport(); - FloatRect target_rect_in_document(2000, 3000, 100, 100); + IntRect target_rect_in_document(2000, 3000, 100, 100); ASSERT_EQ(0.5f, visual_viewport.Scale()); @@ -12009,7 +12017,7 @@ kProgrammaticScroll); EXPECT_FLOAT_EQ(1, visual_viewport.Scale()); - EXPECT_TRUE(visual_viewport.VisibleRectInDocument().Contains( + EXPECT_TRUE(frame_view->GetScrollableArea()->VisibleContentRect().Contains( target_rect_in_document)); } @@ -12023,7 +12031,7 @@ WebRect block_bounds = ComputeBlockBoundHelper(&WebView(), point, false); WebView().AnimateDoubleTapZoom(IntPoint(point), block_bounds); EXPECT_TRUE(WebView().FakeDoubleTapAnimationPendingForTesting()); - FloatPoint target_offset( + IntPoint target_offset( WebView().FakePageScaleAnimationTargetPositionForTesting()); float new_scale = WebView().FakePageScaleAnimationPageScaleForTesting();
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 20d774a..6baa3d4 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -2250,9 +2250,11 @@ else new_scale = PageScaleFactor(); + ScrollableArea* root_viewport = + MainFrameImpl()->GetFrame()->View()->GetScrollableArea(); + // If the caret is offscreen, then animate. - if (!visual_viewport.VisibleRectInDocument().Contains( - caret_bounds_in_content)) + if (!root_viewport->VisibleContentRect().Contains(caret_bounds_in_content)) need_animation = true; // If the box is partially offscreen and it's possible to bring it fully @@ -2261,8 +2263,7 @@ element_bounds_in_content.Width() && visual_viewport.VisibleRect().Height() >= element_bounds_in_content.Height() && - !visual_viewport.VisibleRectInDocument().Contains( - element_bounds_in_content)) + !root_viewport->VisibleContentRect().Contains(element_bounds_in_content)) need_animation = true; if (!need_animation)
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 ada062c..27ec352c 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
@@ -452,8 +452,8 @@ DigestValue digest; if (algorithm_map.csp_hash_algorithm & hash_algorithms_used) { bool digest_success = - ComputeDigest(algorithm_map.algorithm, utf8_source.Data(), - utf8_source.length(), digest); + ComputeDigest(algorithm_map.algorithm, utf8_source.data(), + utf8_source.size(), digest); if (digest_success) { csp_hash_values->push_back( CSPHashValue(algorithm_map.csp_hash_algorithm, digest));
diff --git a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc index d8da1c0..d4ebebc 100644 --- a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc +++ b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc
@@ -34,8 +34,8 @@ String GetSha256String(const String& content) { DigestValue digest; StringUTF8Adaptor utf8_content(content); - bool digest_success = ComputeDigest(kHashAlgorithmSha256, utf8_content.Data(), - utf8_content.length(), digest); + bool digest_success = ComputeDigest(kHashAlgorithmSha256, utf8_content.data(), + utf8_content.size(), digest); if (!digest_success) { return "sha256-..."; }
diff --git a/third_party/blink/renderer/core/frame/visual_viewport.cc b/third_party/blink/renderer/core/frame/visual_viewport.cc index 3076565..6e4bc65 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport.cc +++ b/third_party/blink/renderer/core/frame/visual_viewport.cc
@@ -370,16 +370,6 @@ return FloatRect(FloatPoint(GetScrollOffset()), visible_size); } -FloatRect VisualViewport::VisibleRectInDocument( - IncludeScrollbarsInRect scrollbar_inclusion) const { - if (!MainFrame() || !MainFrame()->View()) - return FloatRect(); - - FloatPoint view_location = - FloatPoint(MainFrame()->View()->GetScrollableArea()->GetScrollOffset()); - return FloatRect(view_location, VisibleRect(scrollbar_inclusion).Size()); -} - FloatPoint VisualViewport::ViewportCSSPixelsToRootFrame( const FloatPoint& point) const { // Note, this is in CSS Pixels so we don't apply scale.
diff --git a/third_party/blink/renderer/core/frame/visual_viewport.h b/third_party/blink/renderer/core/frame/visual_viewport.h index b109fd3..4f93bdc5 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport.h +++ b/third_party/blink/renderer/core/frame/visual_viewport.h
@@ -132,11 +132,6 @@ // +/- zooming). FloatRect VisibleRect(IncludeScrollbarsInRect = kExcludeScrollbars) const; - // Similar to VisibleRect but this returns the rect relative to the main - // document's top-left corner. - FloatRect VisibleRectInDocument( - IncludeScrollbarsInRect = kExcludeScrollbars) const; - // Resets the viewport to initial state. void Reset();
diff --git a/third_party/blink/renderer/core/frame/visual_viewport_test.cc b/third_party/blink/renderer/core/frame/visual_viewport_test.cc index 4208920..33ae138 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport_test.cc +++ b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
@@ -582,32 +582,6 @@ EXPECT_FLOAT_RECT_EQ(expected_rect, visual_viewport.VisibleRect()); } -// Make sure that the visibleRectInDocument method acurately reflects the scale -// and scroll location of the viewport relative to the document. -TEST_P(VisualViewportTest, TestVisibleRectInDocument) { - InitializeWithDesktopSettings(); - WebView()->MainFrameWidget()->Resize(IntSize(100, 400)); - - RegisterMockedHttpURLLoad("200-by-800-viewport.html"); - NavigateTo(base_url_ + "200-by-800-viewport.html"); - - VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); - - // Scale the viewport to 2X and move it. - visual_viewport.SetScale(2); - visual_viewport.SetLocation(FloatPoint(10, 15)); - EXPECT_FLOAT_RECT_EQ(FloatRect(10, 15, 50, 200), - visual_viewport.VisibleRectInDocument()); - - // Scroll the layout viewport. Ensure its offset is reflected in - // visibleRectInDocument(). - LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); - frame_view.LayoutViewport()->SetScrollOffset(ScrollOffset(40, 100), - kProgrammaticScroll); - EXPECT_FLOAT_RECT_EQ(FloatRect(50, 115, 50, 200), - visual_viewport.VisibleRectInDocument()); -} - TEST_P(VisualViewportTest, TestFractionalScrollOffsetIsNotOverwritten) { ScopedFractionalScrollOffsetsForTest fractional_scroll_offsets(true); InitializeWithAndroidSettings(); @@ -2420,7 +2394,9 @@ // Ensure we create effect node for scrollbar properly. TEST_P(VisualViewportTest, EnsureEffectNodeForScrollbars) { - if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) + if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() || + // TODO(wangxianzhu): Should this work for CompositeAfterPaint? + RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) return; InitializeWithAndroidSettings();
diff --git a/third_party/blink/renderer/core/input/keyboard_event_manager.cc b/third_party/blink/renderer/core/input/keyboard_event_manager.cc index 0a8009a..fa4877ef 100644 --- a/third_party/blink/renderer/core/input/keyboard_event_manager.cc +++ b/third_party/blink/renderer/core/input/keyboard_event_manager.cc
@@ -309,11 +309,6 @@ if (event->keyCode() == kVKeyProcessKey) return; - if (event->keyCode() == kVKeySpatNavBack && - DefaultSpatNavBackEventHandler(event)) { - return; - } - if (event->key() == "Tab") { DefaultTabEventHandler(event); } else if (event->key() == "Escape") { @@ -332,8 +327,13 @@ if (event->charCode() == ' ') DefaultSpaceEventHandler(event, possible_focused_node); } else if (event->type() == event_type_names::kKeyup) { - if (event->key() == "Enter") + if (event->key() == "Enter") { DefaultEnterEventHandler(event); + return; + } + + if (event->keyCode() == kVKeySpatNavBack) + DefaultSpatNavBackEventHandler(event); } }
diff --git a/third_party/blink/renderer/core/inspector/devtools_session.cc b/third_party/blink/renderer/core/inspector/devtools_session.cc index 13d2868..6435384 100644 --- a/third_party/blink/renderer/core/inspector/devtools_session.cc +++ b/third_party/blink/renderer/core/inspector/devtools_session.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/core/inspector/devtools_session.h" +#include "base/containers/span.h" #include "third_party/blink/renderer/bindings/core/v8/script_controller.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/use_counter.h" @@ -50,8 +51,8 @@ result->data = std::move(message.binary); } else { WTF::StringUTF8Adaptor adaptor(message.json); - result->data = mojo_base::BigBuffer(base::make_span( - reinterpret_cast<const uint8_t*>(adaptor.Data()), adaptor.length())); + result->data = + mojo_base::BigBuffer(base::as_bytes(base::make_span(adaptor))); } return result; }
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 3055e56..162e924 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -700,7 +700,7 @@ const char kTextControlChanged[] = "Text control changed"; const char kSvgChanged[] = "SVG changed"; const char kScrollbarChanged[] = "Scrollbar changed"; -const char kDisplayLockCommitting[] = "Display lock committing"; +const char kDisplayLock[] = "Display lock"; } // namespace layout_invalidation_reason std::unique_ptr<TracedValue> inspector_layout_invalidation_tracking_event::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 fca953b..566e160 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.h +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.h
@@ -248,7 +248,7 @@ // size related invalidations. extern const char kSvgChanged[]; extern const char kScrollbarChanged[]; -extern const char kDisplayLockCommitting[]; +extern const char kDisplayLock[]; } // namespace layout_invalidation_reason // LayoutInvalidationReasonForTracing is strictly for tracing. Blink logic must
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc index ef8636497..5f64e2c3 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc
@@ -76,7 +76,7 @@ // OverrideContainingBlockContentLogicalWidth/Height are used by e.g. grid // layout. Override sizes are padding box size, not border box, so we must add // borders and scrollbars to compensate. - NGBoxStrut borders_and_scrollbars = + NGBoxStrut border_scrollbar = ComputeBorders(constraint_space, container_node) + NGBlockNode(container).GetScrollbarSizes(); @@ -92,14 +92,14 @@ if (HasOverrideContainingBlockContentLogicalWidth()) { container_border_box_logical_width = OverrideContainingBlockContentLogicalWidth() + - borders_and_scrollbars.InlineSum(); + border_scrollbar.InlineSum(); } else { container_border_box_logical_width = container->LogicalWidth(); } if (HasOverrideContainingBlockContentLogicalHeight()) { container_border_box_logical_height = OverrideContainingBlockContentLogicalHeight() + - borders_and_scrollbars.BlockSum(); + border_scrollbar.BlockSum(); } else { container_border_box_logical_height = container->LogicalHeight(); } @@ -133,10 +133,10 @@ // Run(). Otherwise, NGOutOfFlowLayoutPart may also lay out other objects // it discovers that are part of the same containing block, but those // should get laid out by the actual containing block. - NGOutOfFlowLayoutPart( - &container_builder, css_container->CanContainAbsolutePositionObjects(), - css_container->CanContainFixedPositionObjects(), borders_and_scrollbars, - constraint_space, *container_style, initial_containing_block_fixed_size) + NGOutOfFlowLayoutPart(css_container->CanContainAbsolutePositionObjects(), + css_container->CanContainFixedPositionObjects(), + *container_style, constraint_space, border_scrollbar, + &container_builder, initial_containing_block_fixed_size) .Run(/* only_layout */ this); scoped_refptr<const NGLayoutResult> result = container_builder.ToBoxFragment();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc index c67bec5..9b00e26 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -700,9 +700,8 @@ // Only layout absolute and fixed children if we aren't going to revisit this // layout. if (unpositioned_floats_.IsEmpty()) { - NGOutOfFlowLayoutPart(&container_builder_, Node().IsAbsoluteContainer(), - Node().IsFixedContainer(), borders + scrollbars, - ConstraintSpace(), Style()) + NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), borders + scrollbars, + &container_builder_) .Run(); }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc index 0fcbece..243fdbf 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
@@ -20,6 +20,8 @@ namespace blink { +namespace { + using LineBoxPair = std::pair<const NGPhysicalLineBoxFragment*, const NGPhysicalLineBoxFragment*>; void GatherInlineContainerFragmentsFromLinebox( @@ -31,7 +33,7 @@ if (!descendant.fragment->IsBox()) continue; LayoutObject* key = descendant.fragment->GetLayoutObject(); - // Key for inline is continuation root if it exists. + // Key for inline is the continuation root if it exists. if (key->IsLayoutInline() && key->GetNode()) key = key->GetNode()->GetLayoutObject(); auto it = inline_containing_block_map->find(key); @@ -70,6 +72,8 @@ } } +} // namespace + void NGBoxFragmentBuilder::RemoveChildren() { child_break_tokens_.resize(0); inline_break_tokens_.resize(0); @@ -258,12 +262,12 @@ return base::AdoptRef(new NGLayoutResult(status, this)); } -// Finds InlineContainingBlockGeometry that define inline containing blocks. -// |inline_containing_block_map| is a map whose keys specify which -// inline containing blocks are required. +// Computes the geometry required for any inline containing blocks. +// |inline_containing_block_map| is a map whose keys specify which inline +// containing block geometry is required. void NGBoxFragmentBuilder::ComputeInlineContainerFragments( InlineContainingBlockMap* inline_containing_block_map) { - if (!inline_containing_block_map->size()) + if (inline_containing_block_map->IsEmpty()) return; // This function has detailed knowledge of inline fragment tree structure, @@ -271,8 +275,8 @@ DCHECK_GE(InlineSize(), LayoutUnit()); DCHECK_GE(BlockSize(), LayoutUnit()); - // std::pair.first points to start linebox fragment. - // std::pair.second points to ending linebox fragment. + // std::pair.first points to the start linebox fragment. + // std::pair.second points to the end linebox fragment. using LineBoxPair = std::pair<const NGPhysicalLineBoxFragment*, const NGPhysicalLineBoxFragment*>; HashMap<const LayoutObject*, LineBoxPair> containing_linebox_map; @@ -297,9 +301,8 @@ // split inlines. The inline container fragments might be inside // anonymous boxes. To find inline container fragments, traverse // lineboxes inside anonymous box. - // For more on this special case, see "css container is an inline, - // with inline splitting" comment in - // NGOutOfFlowLayoutPart::LayoutDescendant. + // For more on this special case, see "css container is an inline, with + // inline splitting" comment in NGOutOfFlowLayoutPart::LayoutDescendant. const NGPhysicalOffset box_offset = offsets_[i].ConvertToPhysical( GetWritingMode(), Direction(), ToNGPhysicalSize(Size(), GetWritingMode()), box_fragment->Size());
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc index aad1f91..911faa1 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
@@ -180,9 +180,8 @@ break; } while (true); - NGOutOfFlowLayoutPart(&container_builder_, Node().IsAbsoluteContainer(), - Node().IsFixedContainer(), borders + scrollbars, - ConstraintSpace(), Style()) + NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), borders + scrollbars, + &container_builder_) .Run(); // TODO(mstensho): Propagate baselines.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc index 5c2613bd..b1d6eefc 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
@@ -131,9 +131,8 @@ container_builder_.SetBorders(borders); container_builder_.SetPadding(padding); - NGOutOfFlowLayoutPart(&container_builder_, Node().IsAbsoluteContainer(), - Node().IsFixedContainer(), borders_with_legend, - ConstraintSpace(), Style()) + NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), borders_with_legend, + &container_builder_) .Run(); return container_builder_.ToBoxFragment();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc index 98f0768..e1c45a8a 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
@@ -274,10 +274,9 @@ GiveLinesAndItemsFinalPositionAndSize(); - NGOutOfFlowLayoutPart(&container_builder_, Node().IsAbsoluteContainer(), - Node().IsFixedContainer(), + NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), borders_ + Node().GetScrollbarSizes(), - ConstraintSpace(), Style()) + &container_builder_) .Run(); return container_builder_.ToBoxFragment();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc index 345cd3a..9ae716b7 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -23,17 +23,19 @@ namespace blink { +namespace { + bool IsAnonymousContainer(const LayoutObject* layout_object) { return layout_object->IsAnonymousBlock() && layout_object->CanContainAbsolutePositionObjects(); } -// When containing block is a split inline, Legacy and NG use different -// containers to place OOF descendant. -// Legacy uses the anonymous block generated by inline. -// NG uses the anonymous' parent block, that contains all the anonymous -// continuations. -// This function finds anonymous parent block. +// When the containing block is a split inline, Legacy and NG use different +// containers to place the OOF descendant: +// - Legacy uses the anonymous block generated by inline. +// - NG uses the anonymous' parent block, that contains all the anonymous +// continuations. +// This function finds the correct anonymous parent block. LayoutBoxModelObject* GetOOFContainingBlockFromAnonymous( const LayoutObject* anonymous_block, EPosition child_position) { @@ -61,13 +63,27 @@ absolute_containing_block->GetNode()->GetLayoutObject()); } +} // namespace + NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( - NGBoxFragmentBuilder* container_builder, + const NGBlockNode& container_node, + const NGConstraintSpace& container_space, + const NGBoxStrut& border_scrollbar, + NGBoxFragmentBuilder* container_builder) + : NGOutOfFlowLayoutPart(container_node.IsAbsoluteContainer(), + container_node.IsFixedContainer(), + container_node.Style(), + container_space, + border_scrollbar, + container_builder) {} + +NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( bool contains_absolute, bool contains_fixed, - const NGBoxStrut& border_scrollbar, - const NGConstraintSpace& container_space, const ComputedStyle& container_style, + const NGConstraintSpace& container_space, + const NGBoxStrut& border_scrollbar, + NGBoxFragmentBuilder* container_builder, base::Optional<NGLogicalSize> initial_containing_block_fixed_size) : container_builder_(container_builder), contains_absolute_(contains_absolute), @@ -77,21 +93,9 @@ ->HasPositionedObjects()) return; - NGPhysicalBoxStrut physical_border_scrollbar = - border_scrollbar.ConvertToPhysical(container_style.GetWritingMode(), - container_style.Direction()); - default_containing_block_.style = &container_style; default_containing_block_.content_size_for_absolute = - container_builder_->Size(); - default_containing_block_.content_size_for_absolute.inline_size = - std::max(default_containing_block_.content_size_for_absolute.inline_size - - border_scrollbar.InlineSum(), - LayoutUnit()); - default_containing_block_.content_size_for_absolute.block_size = - std::max(default_containing_block_.content_size_for_absolute.block_size - - border_scrollbar.BlockSum(), - LayoutUnit()); + ShrinkAvailableSize(container_builder_->Size(), border_scrollbar); default_containing_block_.content_size_for_fixed = initial_containing_block_fixed_size ? *initial_containing_block_fixed_size @@ -99,6 +103,10 @@ default_containing_block_.container_offset = NGLogicalOffset( border_scrollbar.inline_start, border_scrollbar.block_start); + + NGPhysicalBoxStrut physical_border_scrollbar = + border_scrollbar.ConvertToPhysical(container_style.GetWritingMode(), + container_style.Direction()); default_containing_block_.physical_container_offset = NGPhysicalOffset( physical_border_scrollbar.left, physical_border_scrollbar.top); } @@ -116,10 +124,10 @@ return; // Special case: containing block is a split inline. - // If current container was generated by a split inline, - // do not position descendants inside this container. Let its - // non-anonymous parent handle it. Only parent has geometry information - // needed to compute containing block geometry. + // If current container was generated by a split inline, do not position + // descendants inside this container. Let its non-anonymous parent handle it. + // Only parent has geometry information needed to compute containing block + // geometry. // See "Special case: oof css container" comment for detailed description. if (descendant_candidates.size() > 0 && current_container && !only_layout && IsAnonymousContainer(current_container)) { @@ -225,14 +233,14 @@ return true; } -NGOutOfFlowLayoutPart::ContainingBlockInfo +const NGOutOfFlowLayoutPart::ContainingBlockInfo& NGOutOfFlowLayoutPart::GetContainingBlockInfo( const NGOutOfFlowPositionedDescendant& descendant) const { - // TODO remove containing_blocks_map_.Contains - if (descendant.inline_container && - containing_blocks_map_.Contains(descendant.inline_container)) { - DCHECK(containing_blocks_map_.Contains(descendant.inline_container)); - return containing_blocks_map_.at(descendant.inline_container); + if (descendant.inline_container) { + const auto it = containing_blocks_map_.find(descendant.inline_container); + // TODO(atotic): Make this if-condition a DCHECK. + if (it != containing_blocks_map_.end()) + return it->value; } return default_containing_block_; } @@ -432,7 +440,8 @@ descendant.node.GetLayoutBox()->ContainingBlock()) || descendant.node.GetLayoutBox()->ContainingBlock()->IsTable()); - ContainingBlockInfo container_info = GetContainingBlockInfo(descendant); + const ContainingBlockInfo& container_info = + GetContainingBlockInfo(descendant); const ComputedStyle& descendant_style = descendant.node.Style(); WritingMode container_writing_mode(container_info.style->GetWritingMode());
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h index 1e9648b..09982131 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h +++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h
@@ -33,26 +33,31 @@ STACK_ALLOCATED(); public: - // The container_builder, borders_and_scrollers, container_space and - // container_style parameters are all with respect to the containing block of - // the relevant out-of-flow positioned descendants. If the CSS "containing - // block" of such an out-of-flow positioned descendant isn't a true block (but - // e.g. a relatively positioned inline instead), the containing block here is + NGOutOfFlowLayoutPart(const NGBlockNode& container_node, + const NGConstraintSpace& container_space, + const NGBoxStrut& border_scrollbar, + NGBoxFragmentBuilder* container_builder); + + // The |container_builder|, |border_scrollbar|, |container_space|, and + // |container_style| parameters are all with respect to the containing block + // of the relevant out-of-flow positioned descendants. If the CSS "containing + // block" of such an out-of-flow positioned descendant isn't a true block + // (e.g. a relatively positioned inline instead), the containing block here is // the containing block of said non-block. NGOutOfFlowLayoutPart( - NGBoxFragmentBuilder* container_builder, bool contains_absolute, bool contains_fixed, - const NGBoxStrut& borders_and_scrollers, - const NGConstraintSpace& container_space, const ComputedStyle& container_style, + const NGConstraintSpace& container_space, + const NGBoxStrut& border_scrollbar, + NGBoxFragmentBuilder* container_builder, base::Optional<NGLogicalSize> initial_containing_block_fixed_size = base::nullopt); - // Normally this function lays out and positions all out-of-flow objects - // from the container_builder and additional ones it discovers through laying - // out those objects. However, if only_layout is specified, only that object - // will get laid out; any additional ones will be stored as out-of-flow + // Normally this function lays out and positions all out-of-flow objects from + // the container_builder and additional ones it discovers through laying out + // those objects. However, if only_layout is specified, only that object will + // get laid out; any additional ones will be stored as out-of-flow // descendants in the builder for use via // LayoutResult::OutOfFlowPositionedDescendants. void Run(const LayoutBox* only_layout = nullptr); @@ -92,7 +97,7 @@ bool SweepLegacyDescendants(HashSet<const LayoutObject*>* placed_objects); - ContainingBlockInfo GetContainingBlockInfo( + const ContainingBlockInfo& GetContainingBlockInfo( const NGOutOfFlowPositionedDescendant&) const; void ComputeInlineContainingBlocks( @@ -118,10 +123,10 @@ const NGAbsolutePhysicalPosition& node_position); NGBoxFragmentBuilder* container_builder_; - bool contains_absolute_; - bool contains_fixed_; ContainingBlockInfo default_containing_block_; HashMap<const LayoutObject*, ContainingBlockInfo> containing_blocks_map_; + bool contains_absolute_; + bool contains_fixed_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc index 8d88234..10750034 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_page_layout_algorithm.cc
@@ -71,9 +71,8 @@ container_builder_.SetBorders(ComputeBorders(ConstraintSpace(), Node())); container_builder_.SetPadding(ComputePadding(ConstraintSpace(), Style())); - NGOutOfFlowLayoutPart(&container_builder_, Node().IsAbsoluteContainer(), - Node().IsFixedContainer(), borders + scrollbars, - ConstraintSpace(), Style()) + NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), borders + scrollbars, + &container_builder_) .Run(); // TODO(mstensho): Propagate baselines.
diff --git a/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc b/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc index 0e97a54..19c8fcfb 100644 --- a/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc +++ b/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc
@@ -72,9 +72,7 @@ #include "third_party/blink/renderer/platform/graphics/filters/filter.h" #include "third_party/blink/renderer/platform/graphics/filters/source_graphic.h" #include "third_party/blink/renderer/platform/graphics/graphics_types.h" - -#include <math.h> -#include <memory> +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -567,8 +565,8 @@ ts << "\n"; // Creating a placeholder filter which is passed to the builder. FloatRect dummy_rect; - Filter* dummy_filter = - Filter::Create(dummy_rect, dummy_rect, 1, Filter::kBoundingBox); + auto* dummy_filter = MakeGarbageCollected<Filter>(dummy_rect, dummy_rect, 1, + Filter::kBoundingBox); SVGFilterBuilder builder(dummy_filter->GetSourceGraphic()); builder.BuildGraph(dummy_filter, ToSVGFilterElement(*filter->GetElement()), dummy_rect);
diff --git a/third_party/blink/renderer/core/loader/link_loader.cc b/third_party/blink/renderer/core/loader/link_loader.cc index 0ae76cb7..60a0f4bf3 100644 --- a/third_party/blink/renderer/core/loader/link_loader.cc +++ b/third_party/blink/renderer/core/loader/link_loader.cc
@@ -31,7 +31,7 @@ #include "third_party/blink/renderer/core/loader/link_loader.h" -#include "third_party/blink/public/platform/web_prerender.h" +#include "third_party/blink/public/common/prerender/prerender_rel_type.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/use_counter.h"
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc index 3b3bccc..3058d24 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
@@ -61,17 +61,14 @@ const ComputedStyle& style = layout_object.StyleRef(); - if (RequiresCompositingForTransform(layout_object)) + if (RequiresCompositingFor3DTransform(layout_object)) reasons |= CompositingReason::k3DTransform; if (style.BackfaceVisibility() == EBackfaceVisibility::kHidden) reasons |= CompositingReason::kBackfaceVisibilityHidden; reasons |= CompositingReasonsForAnimation(style); - - if (style.HasWillChangeCompositingHint() && - !style.SubtreeWillChangeContents()) - reasons |= CompositingReason::kWillChangeCompositingHint; + reasons |= CompositingReasonsForWillChange(style); if (style.UsedTransformStyle3D() == ETransformStyle3D::kPreserve3d) reasons |= CompositingReason::kPreserve3DWith3DDescendants; @@ -122,15 +119,12 @@ return CompositingReason::kNone; const ComputedStyle& style = object.StyleRef(); - auto reasons = CompositingReasonsForAnimation(style); + auto reasons = CompositingReasonsForAnimation(style) | + CompositingReasonsForWillChange(style); - if (RequiresCompositingForTransform(object)) + if (RequiresCompositingFor3DTransform(object)) reasons |= CompositingReason::k3DTransform; - if (style.HasWillChangeCompositingHint() && - !style.SubtreeWillChangeContents()) - reasons |= CompositingReason::kWillChangeCompositingHint; - auto* layer = ToLayoutBoxModelObject(object).Layer(); if (layer->Has3DTransformedDescendant()) { if (style.HasPerspective()) @@ -148,7 +142,7 @@ return reasons; } -bool CompositingReasonFinder::RequiresCompositingForTransform( +bool CompositingReasonFinder::RequiresCompositingFor3DTransform( const LayoutObject& layout_object) { // Note that we ask the layoutObject if it has a transform, because the style // may have transforms, but the layoutObject may be an inline that doesn't @@ -213,39 +207,38 @@ CompositingReasons CompositingReasonFinder::CompositingReasonsForAnimation( const ComputedStyle& style) { CompositingReasons reasons = CompositingReason::kNone; - if (RequiresCompositingForTransformAnimation(style)) + if (style.SubtreeWillChangeContents()) + return reasons; + + if (style.HasCurrentTransformAnimation()) reasons |= CompositingReason::kActiveTransformAnimation; - if (RequiresCompositingForOpacityAnimation(style)) + if (style.HasCurrentOpacityAnimation()) reasons |= CompositingReason::kActiveOpacityAnimation; - if (RequiresCompositingForFilterAnimation(style)) + if (style.HasCurrentFilterAnimation()) reasons |= CompositingReason::kActiveFilterAnimation; - if (RequiresCompositingForBackdropFilterAnimation(style)) + if (style.HasCurrentBackdropFilterAnimation()) reasons |= CompositingReason::kActiveBackdropFilterAnimation; return reasons; } -bool CompositingReasonFinder::RequiresCompositingForOpacityAnimation( +CompositingReasons CompositingReasonFinder::CompositingReasonsForWillChange( const ComputedStyle& style) { - return style.HasCurrentOpacityAnimation() && - !style.SubtreeWillChangeContents(); -} + CompositingReasons reasons = CompositingReason::kNone; + if (style.SubtreeWillChangeContents()) + return reasons; -bool CompositingReasonFinder::RequiresCompositingForFilterAnimation( - const ComputedStyle& style) { - return style.HasCurrentFilterAnimation() && - !style.SubtreeWillChangeContents(); -} + if (style.HasWillChangeTransformHint()) + reasons |= CompositingReason::kWillChangeTransform; + if (style.HasWillChangeOpacityHint()) + reasons |= CompositingReason::kWillChangeOpacity; -bool CompositingReasonFinder::RequiresCompositingForBackdropFilterAnimation( - const ComputedStyle& style) { - return style.HasCurrentBackdropFilterAnimation() && - !style.SubtreeWillChangeContents(); -} + // kWillChangeOther is needed only when neither kWillChangeTransform nor + // kWillChangeOpacity is set. + if (reasons == CompositingReason::kNone && + style.HasWillChangeCompositingHint()) + reasons |= CompositingReason::kWillChangeOther; -bool CompositingReasonFinder::RequiresCompositingForTransformAnimation( - const ComputedStyle& style) { - return style.HasCurrentTransformAnimation() && - !style.SubtreeWillChangeContents(); + return reasons; } bool CompositingReasonFinder::RequiresCompositingForRootScroller(
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h index fd0fa32..397600f 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h +++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h
@@ -37,12 +37,9 @@ static bool RequiresCompositingForScrollableFrame(const LayoutView&); static CompositingReasons CompositingReasonsForAnimation( const ComputedStyle&); - static bool RequiresCompositingForOpacityAnimation(const ComputedStyle&); - static bool RequiresCompositingForFilterAnimation(const ComputedStyle&); - static bool RequiresCompositingForBackdropFilterAnimation( + static CompositingReasons CompositingReasonsForWillChange( const ComputedStyle&); - static bool RequiresCompositingForTransformAnimation(const ComputedStyle&); - static bool RequiresCompositingForTransform(const LayoutObject&); + static bool RequiresCompositingFor3DTransform(const LayoutObject&); static bool RequiresCompositingForRootScroller(const PaintLayer&); static bool RequiresCompositingForScrollTimeline(const PaintLayer&);
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc index 1e9800b0..039fbb03 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc
@@ -144,32 +144,6 @@ ->GetCompositingState()); } -TEST_F(CompositingReasonFinderTest, RequiresCompositingForTransformAnimation) { - scoped_refptr<ComputedStyle> style = ComputedStyle::Create(); - style->SetSubtreeWillChangeContents(false); - - style->SetHasCurrentTransformAnimation(false); - EXPECT_FALSE( - CompositingReasonFinder::RequiresCompositingForTransformAnimation( - *style)); - - style->SetHasCurrentTransformAnimation(true); - EXPECT_TRUE(CompositingReasonFinder::RequiresCompositingForTransformAnimation( - *style)); - - style->SetSubtreeWillChangeContents(true); - - style->SetHasCurrentTransformAnimation(false); - EXPECT_FALSE( - CompositingReasonFinder::RequiresCompositingForTransformAnimation( - *style)); - - style->SetHasCurrentTransformAnimation(true); - EXPECT_FALSE( - CompositingReasonFinder::RequiresCompositingForTransformAnimation( - *style)); -} - TEST_F(CompositingReasonFinderTest, CompositingReasonsForAnimation) { scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
diff --git a/third_party/blink/renderer/core/paint/filter_effect_builder.cc b/third_party/blink/renderer/core/paint/filter_effect_builder.cc index 5ab79f8..63acec2 100644 --- a/third_party/blink/renderer/core/paint/filter_effect_builder.cc +++ b/third_party/blink/renderer/core/paint/filter_effect_builder.cc
@@ -45,6 +45,7 @@ #include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h" #include "third_party/blink/renderer/platform/graphics/filters/source_graphic.h" #include "third_party/blink/renderer/platform/graphics/interpolation_space.h" +#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/wtf/math_extras.h" namespace blink { @@ -134,7 +135,7 @@ bool input_tainted) const { // Create a parent filter for shorthand filters. These have already been // scaled by the CSS code for page zoom, so scale is 1.0 here. - Filter* parent_filter = Filter::Create(1.0f); + auto* parent_filter = MakeGarbageCollected<Filter>(1.0f); FilterEffect* previous_effect = parent_filter->GetSourceGraphic(); if (input_tainted) previous_effect->SetOriginTainted(); @@ -160,22 +161,22 @@ case FilterOperation::GRAYSCALE: { Vector<float> input_parameters = GrayscaleMatrix( To<BasicColorMatrixFilterOperation>(filter_operation)->Amount()); - effect = FEColorMatrix::Create(parent_filter, FECOLORMATRIX_TYPE_MATRIX, - input_parameters); + effect = MakeGarbageCollected<FEColorMatrix>( + parent_filter, FECOLORMATRIX_TYPE_MATRIX, input_parameters); break; } case FilterOperation::SEPIA: { Vector<float> input_parameters = SepiaMatrix( To<BasicColorMatrixFilterOperation>(filter_operation)->Amount()); - effect = FEColorMatrix::Create(parent_filter, FECOLORMATRIX_TYPE_MATRIX, - input_parameters); + effect = MakeGarbageCollected<FEColorMatrix>( + parent_filter, FECOLORMATRIX_TYPE_MATRIX, input_parameters); break; } case FilterOperation::SATURATE: { Vector<float> input_parameters; input_parameters.push_back(clampTo<float>( To<BasicColorMatrixFilterOperation>(filter_operation)->Amount())); - effect = FEColorMatrix::Create( + effect = MakeGarbageCollected<FEColorMatrix>( parent_filter, FECOLORMATRIX_TYPE_SATURATE, input_parameters); break; } @@ -183,7 +184,7 @@ Vector<float> input_parameters; input_parameters.push_back(clampTo<float>( To<BasicColorMatrixFilterOperation>(filter_operation)->Amount())); - effect = FEColorMatrix::Create( + effect = MakeGarbageCollected<FEColorMatrix>( parent_filter, FECOLORMATRIX_TYPE_HUEROTATE, input_parameters); break; } @@ -200,9 +201,9 @@ transfer_function.table_values = transfer_parameters; ComponentTransferFunction null_function; - effect = FEComponentTransfer::Create(parent_filter, transfer_function, - transfer_function, - transfer_function, null_function); + effect = MakeGarbageCollected<FEComponentTransfer>( + parent_filter, transfer_function, transfer_function, + transfer_function, null_function); break; } case FilterOperation::OPACITY: { @@ -216,9 +217,9 @@ transfer_function.table_values = transfer_parameters; ComponentTransferFunction null_function; - effect = FEComponentTransfer::Create(parent_filter, null_function, - null_function, null_function, - transfer_function); + effect = MakeGarbageCollected<FEComponentTransfer>( + parent_filter, null_function, null_function, null_function, + transfer_function); break; } case FilterOperation::BRIGHTNESS: { @@ -230,9 +231,9 @@ transfer_function.intercept = 0; ComponentTransferFunction null_function; - effect = FEComponentTransfer::Create(parent_filter, transfer_function, - transfer_function, - transfer_function, null_function); + effect = MakeGarbageCollected<FEComponentTransfer>( + parent_filter, transfer_function, transfer_function, + transfer_function, null_function); break; } case FilterOperation::CONTRAST: { @@ -245,31 +246,31 @@ transfer_function.intercept = -0.5 * amount + 0.5; ComponentTransferFunction null_function; - effect = FEComponentTransfer::Create(parent_filter, transfer_function, - transfer_function, - transfer_function, null_function); + effect = MakeGarbageCollected<FEComponentTransfer>( + parent_filter, transfer_function, transfer_function, + transfer_function, null_function); break; } case FilterOperation::BLUR: { float std_deviation = FloatValueForLength( To<BlurFilterOperation>(filter_operation)->StdDeviation(), 0); - effect = - FEGaussianBlur::Create(parent_filter, std_deviation, std_deviation); + effect = MakeGarbageCollected<FEGaussianBlur>( + parent_filter, std_deviation, std_deviation); break; } case FilterOperation::DROP_SHADOW: { const ShadowData& shadow = To<DropShadowFilterOperation>(*filter_operation).Shadow(); - effect = FEDropShadow::Create(parent_filter, shadow.Blur(), - shadow.Blur(), shadow.X(), shadow.Y(), - shadow.GetColor().GetColor(), 1); + effect = MakeGarbageCollected<FEDropShadow>( + parent_filter, shadow.Blur(), shadow.Blur(), shadow.X(), shadow.Y(), + shadow.GetColor().GetColor(), 1); break; } case FilterOperation::BOX_REFLECT: { BoxReflectFilterOperation* box_reflect_operation = To<BoxReflectFilterOperation>(filter_operation); - effect = FEBoxReflect::Create(parent_filter, - box_reflect_operation->Reflection()); + effect = MakeGarbageCollected<FEBoxReflect>( + parent_filter, box_reflect_operation->Reflection()); break; } default: @@ -436,8 +437,8 @@ SVGUnitTypes::kSvgUnitTypeObjectboundingbox; Filter::UnitScaling unit_scaling = primitive_bounding_box_mode ? Filter::kBoundingBox : Filter::kUserSpace; - Filter* result = - Filter::Create(reference_box_, filter_region, zoom_, unit_scaling); + auto* result = MakeGarbageCollected<Filter>(reference_box_, filter_region, + zoom_, unit_scaling); if (!previous_effect) previous_effect = result->GetSourceGraphic(); SVGFilterBuilder builder(previous_effect, node_map, fill_flags_,
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index f5fb431..4be210f 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -616,6 +616,24 @@ style.TransformOriginZ()); } +// TODO(crbug.com/900241): Remove this function and let the caller use +// CompositingReason::kDirectReasonForTransformProperty directly. +static CompositingReasons CompositingReasonsForTransformProperty() { + CompositingReasons reasons = + CompositingReason::kDirectReasonsForTransformProperty; + // TODO(crbug.com/900241): Check for nodes for each KeyframeModel target + // property instead of creating all nodes and only create a transform/ + // effect/filter node if needed. + reasons |= CompositingReason::kComboActiveAnimation; + // We also need to create transform node if the opacity node is created for + // will-change:opacity to avoid raster invalidation (caused by otherwise a + // created/deleted effect node) when we start/stop an opacity animation. + // https://crbug.com/942681 + if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) + reasons |= CompositingReason::kWillChangeOpacity; + return reasons; +} + static bool NeedsTransform(const LayoutObject& object, CompositingReasons direct_compositing_reasons) { if (object.IsText()) @@ -626,12 +644,7 @@ object.StyleRef().BackfaceVisibility() == EBackfaceVisibility::kHidden) return true; - // TODO(crbug.com/900241): Currently kDirectReasonsForTransformProperty - // includes all will-change compositing hints including opacity. This is - // needed to avoid creating/deleting transform nodes on start/end of an - // opacity animation. https://crbug.com/942681 - if (direct_compositing_reasons & - CompositingReason::kDirectReasonsForTransformProperty) + if (direct_compositing_reasons & CompositingReasonsForTransformProperty()) return true; if (!object.IsBox()) @@ -694,7 +707,7 @@ } state.direct_compositing_reasons = full_context_.direct_compositing_reasons & - CompositingReason::kDirectReasonsForTransformProperty; + CompositingReasonsForTransformProperty(); } } @@ -748,21 +761,24 @@ return false; } +// TODO(crbug.com/900241): Remove this function and let the caller use +// CompositingReason::kDirectReasonForEffectProperty directly. static CompositingReasons CompositingReasonsForEffectProperty() { - // TODO(crbug.com/900241): See the comment in compositing_reasons.h about - // the bug for the reason of this. - if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { - return CompositingReason::kDirectReasonsForEffectProperty; - } - // We also need to create effect node if the transform node is created for - // will-change to avoid raster invalidation (caused by otherwise a created/ - // deleted effect node) when we start/stop a transform animation. - // https://crbug.com/942681 + CompositingReasons reasons = + CompositingReason::kDirectReasonsForEffectProperty; if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) { - return CompositingReason::kDirectReasonsForEffectProperty | - CompositingReason::kWillChangeCompositingHint; + // TODO(crbug.com/900241): Check for nodes for each KeyframeModel target + // property instead of creating all nodes and only create a transform/ + // effect/filter node if needed. + reasons |= CompositingReason::kComboActiveAnimation; + // We also need to create effect node if the transform node is created for + // will-change:transform to avoid raster invalidation (caused by otherwise a + // created/deleted effect node) when we start/stop a transform animation. + // https://crbug.com/942681 + if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) + reasons |= CompositingReason::kWillChangeTransform; } - return CompositingReason::kActiveOpacityAnimation; + return reasons; } static bool NeedsEffect(const LayoutObject& object, @@ -827,7 +843,7 @@ if (!style.BackdropFilter().IsEmpty()) return true; - if (style.Opacity() != 1.0f || style.HasWillChangeOpacityHint()) + if (style.Opacity() != 1.0f) return true; if (direct_compositing_reasons & CompositingReasonsForEffectProperty()) @@ -969,12 +985,9 @@ // // Currently, we use the existence of this id to check if effect nodes // have been created for animations on this element. - // TODO(flackr): Check for nodes for each KeyframeModel target - // property instead of creating all nodes and create each type of - // node as needed, https://crbug.com/900241 state.direct_compositing_reasons = full_context_.direct_compositing_reasons & - CompositingReason::kDirectReasonsForEffectProperty; + CompositingReasonsForEffectProperty(); if (state.direct_compositing_reasons) { state.compositor_element_id = CompositorElementIdFromUniqueObjectId( object_.UniqueId(), CompositorElementIdNamespace::kPrimaryEffect); @@ -1081,21 +1094,26 @@ return page->GetLinkHighlights().NeedsHighlightEffect(object); } +// TODO(crbug.com/900241): Remove this function and let the caller use +// CompositingReason::kDirectReasonForFilterProperty directly. static CompositingReasons CompositingReasonsForFilterProperty() { - // TODO(crbug.com/900241): See the comment in compositing_reasons.h about - // the bug for the reason of this. - if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { - return CompositingReason::kDirectReasonsForFilterProperty; - } - // We also need to create filter node if the transform node is created for - // will-change to avoid raster invalidation (caused by otherwise a created/ - // deleted filter node) when we start/stop a transform/opacity animation. - // https://crbug.com/942681 + CompositingReasons reasons = + CompositingReason::kDirectReasonsForFilterProperty; if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) { - return CompositingReason::kDirectReasonsForFilterProperty | - CompositingReason::kWillChangeCompositingHint; + // TODO(crbug.com/900241): Check for nodes for each KeyframeModel target + // property instead of creating all nodes and only create a transform/ + // effect/filter node if needed. + reasons |= CompositingReason::kComboActiveAnimation; + // We also need to create filter node if the transform/effect node is + // created for will-change:transform/opacity to avoid raster invalidation + // (caused by otherwise a created/deleted filter node) when we start/stop a + // transform/opacity animation. https://crbug.com/942681 + if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { + reasons |= CompositingReason::kWillChangeTransform | + CompositingReason::kWillChangeOpacity; + } } - return CompositingReason::kActiveFilterAnimation; + return reasons; } static bool NeedsFilter(const LayoutObject& object, @@ -1170,7 +1188,7 @@ // current. state.direct_compositing_reasons = full_context_.direct_compositing_reasons & - CompositingReason::kDirectReasonsForFilterProperty; + CompositingReasonsForFilterProperty(); state.compositor_element_id = CompositorElementIdFromUniqueObjectId( object_.UniqueId(), CompositorElementIdNamespace::kEffectFilter);
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc index 4cbfce4..2715a9be 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
@@ -810,6 +810,16 @@ GetDocument().View()->GetLayoutView()); } +TEST_P(PaintPropertyTreeBuilderTest, NoEffectAndFilterForNonStackingContext) { + SetBodyInnerHTML(R"HTML( + <div id="target" style="will-change: right; backface-visibility: hidden"> + </div> + )HTML"); + EXPECT_NE(nullptr, PaintPropertiesForElement("target")->Transform()); + EXPECT_EQ(nullptr, PaintPropertiesForElement("target")->Effect()); + EXPECT_EQ(nullptr, PaintPropertiesForElement("target")->Filter()); +} + TEST_P(PaintPropertyTreeBuilderTest, RelativePositionInline) { LoadTestData("relative-position-inline.html"); @@ -4711,7 +4721,7 @@ transform-origin: 75% 75% 0; } #willChange { - will-change: opacity; + will-change: transform; transform-origin: 75% 75% 0; } </style> @@ -4750,7 +4760,7 @@ transform-origin: 50% 50% 0; } #willChange { - will-change: opacity; + will-change: transform; transform-origin: 50% 50% 0; } </style> @@ -5526,13 +5536,11 @@ opacity_element->setAttribute(html_names::kStyleAttr, "opacity: 0.5"); GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint(); - if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) { - // TODO(crbug.com/900241): In BlinkGenPropertyTrees/CompositeAfterPaint we - // create effect and filter nodes when the transform node needs compositing, - // for crbug.com/942681. - // TODO(crbug.com/943671): CompositeAfterPaint also does this but the layer - // is marked needing repaint because of paint invalidation. Figure out if - // this is an over invalidation. + if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() && + !RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { + // TODO(crbug.com/900241): In BlinkGenPropertyTrees (but not + // CompoisteAfterPaint) we create effect and filter nodes when the transform + // node needs compositing for will-change:transform, for crbug.com/942681. EXPECT_FALSE(ToLayoutBoxModelObject(target)->Layer()->NeedsRepaint()); } else { // All paint chunks contained by the new opacity effect node need to be @@ -6426,9 +6434,10 @@ TEST_P(PaintPropertyTreeBuilderTest, SimpleOpacityChangeDoesNotCausePacUpdate) { // This is a BGPT test only. - // TODO(vmpstr): For CAP, we don't seem to get a cc_effect, which we need to - // investigate. - if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) + if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() || + // TODO(vmpstr): For CompositeAfterPaint, we don't seem to get a + // cc_effect, which we need to investigate. + RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) return; SetHtmlInnerHTML(R"HTML( @@ -6488,7 +6497,9 @@ TEST_P(PaintPropertyTreeBuilderTest, SimpleScrollChangeDoesNotCausePacUpdate) { // This is a BGPT test only. - if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) + if (!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() || + // TODO(vmpstr): Make this test pass for CompositeAfterPaint. + RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) return; SetHtmlInnerHTML(R"HTML(
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc index a289b3c..6cc767df 100644 --- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc +++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -281,6 +281,7 @@ context.paint_invalidator_context.NeedsVisualRectUpdate(object); } +#if DCHECK_IS_ON() void PrePaintTreeWalk::CheckTreeBuilderContextState( const LayoutObject& object, const PrePaintTreeWalkContext& parent_context) { @@ -290,20 +291,21 @@ return; } - CHECK(!object.NeedsPaintPropertyUpdate()); - CHECK(!object.DescendantNeedsPaintPropertyUpdate()); - CHECK(!object.DescendantNeedsPaintOffsetAndVisualRectUpdate()); + DCHECK(!object.NeedsPaintPropertyUpdate()); + DCHECK(!object.DescendantNeedsPaintPropertyUpdate()); + DCHECK(!object.DescendantNeedsPaintOffsetAndVisualRectUpdate()); if (parent_context.paint_invalidator_context.NeedsVisualRectUpdate(object)) { // Note that if paint_invalidator_context's NeedsVisualRectUpdate(object) is - // true, we definitely want to CHECK. However, we would also like to know + // true, we definitely want to DCHECK. However, we would also like to know // the value of object.NeedsPaintOffsetAndVisualRectUpdate(), hence one of - // the two CHECKs below will definitely trigger, and depending on which one + // the two DCHECKs below will definitely trigger, and depending on which one // does we will know the value. - CHECK(object.NeedsPaintOffsetAndVisualRectUpdate()); - CHECK(!object.NeedsPaintOffsetAndVisualRectUpdate()); + DCHECK(object.NeedsPaintOffsetAndVisualRectUpdate()); + DCHECK(!object.NeedsPaintOffsetAndVisualRectUpdate()); } - CHECK(false) << "Unknown reason."; + NOTREACHED(); } +#endif void PrePaintTreeWalk::WalkInternal(const LayoutObject& object, PrePaintTreeWalkContext& context) { @@ -424,8 +426,9 @@ return; } - // The following is for debugging crbug.com/816810. +#if DCHECK_IS_ON() CheckTreeBuilderContextState(object, parent_context()); +#endif // Early out from the tree walk if possible. if (!needs_tree_builder_context_update && !ObjectRequiresPrePaint(object) &&
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h index f41d965..74a0a35 100644 --- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h +++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h
@@ -86,8 +86,10 @@ static bool ContextRequiresTreeBuilderContext(const PrePaintTreeWalkContext&, const LayoutObject&); +#if DCHECK_IS_ON() void CheckTreeBuilderContextState(const LayoutObject&, const PrePaintTreeWalkContext&); +#endif const PrePaintTreeWalkContext& ContextAt(wtf_size_t index) { DCHECK_LT(index, context_storage_.size());
diff --git a/third_party/blink/renderer/core/streams/miscellaneous_operations_test.cc b/third_party/blink/renderer/core/streams/miscellaneous_operations_test.cc index 82ecdfc3..c21a934 100644 --- a/third_party/blink/renderer/core/streams/miscellaneous_operations_test.cc +++ b/third_party/blink/renderer/core/streams/miscellaneous_operations_test.cc
@@ -97,8 +97,7 @@ int argc = 0, v8::Local<v8::Value> argv[] = nullptr) { String js = String("({start: ") + function_definition + "})" + '\0'; - ScriptValue underlying_value = - EvalWithPrintingError(scope, WTF::StringUTF8Adaptor(js).Data()); + ScriptValue underlying_value = EvalWithPrintingError(scope, js.Utf8().data()); auto underlying_object = underlying_value.V8Value().As<v8::Object>(); auto* algo = CreateAlgorithmFromUnderlyingMethod( scope->GetScriptState(), underlying_object, "start",
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index c10b31c..e5f0efa 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -885,10 +885,10 @@ other.HasCurrentBackdropFilterAnimation() || SubtreeWillChangeContents() != other.SubtreeWillChangeContents() || BackfaceVisibility() != other.BackfaceVisibility() || - HasWillChangeCompositingHint() != other.HasWillChangeCompositingHint() || UsedTransformStyle3D() != other.UsedTransformStyle3D() || ContainsPaint() != other.ContainsPaint() || - IsOverflowVisible() != other.IsOverflowVisible()) { + IsOverflowVisible() != other.IsOverflowVisible() || + WillChangeProperties() != other.WillChangeProperties()) { diff.SetCompositingReasonsChanged(); } } @@ -999,46 +999,51 @@ SetContentInternal(content_data); } -bool ComputedStyle::HasWillChangeCompositingHint() const { - for (const auto& property : WillChangeProperties()) { - switch (property) { - case CSSPropertyID::kOpacity: - case CSSPropertyID::kTransform: - case CSSPropertyID::kAliasWebkitTransform: - case CSSPropertyID::kTranslate: - case CSSPropertyID::kScale: - case CSSPropertyID::kRotate: - case CSSPropertyID::kTop: - case CSSPropertyID::kLeft: - case CSSPropertyID::kBottom: - case CSSPropertyID::kRight: - return true; - default: - break; - } +static bool IsWillChangeTransformHintProperty(CSSPropertyID property) { + switch (property) { + case CSSPropertyID::kTransform: + case CSSPropertyID::kAliasWebkitTransform: + case CSSPropertyID::kPerspective: + case CSSPropertyID::kTranslate: + case CSSPropertyID::kScale: + case CSSPropertyID::kRotate: + case CSSPropertyID::kOffsetPath: + case CSSPropertyID::kOffsetPosition: + return true; + default: + break; } return false; } -bool ComputedStyle::HasWillChangeTransformHint() const { - for (const auto& property : WillChangeProperties()) { - switch (property) { - case CSSPropertyID::kTransform: - case CSSPropertyID::kAliasWebkitTransform: - case CSSPropertyID::kPerspective: - case CSSPropertyID::kTranslate: - case CSSPropertyID::kScale: - case CSSPropertyID::kRotate: - case CSSPropertyID::kOffsetPath: - case CSSPropertyID::kOffsetPosition: - return true; - default: - break; - } +static bool IsWillChangeCompositingHintProperty(CSSPropertyID property) { + if (IsWillChangeTransformHintProperty(property)) + return true; + switch (property) { + case CSSPropertyID::kOpacity: + case CSSPropertyID::kTop: + case CSSPropertyID::kLeft: + case CSSPropertyID::kBottom: + case CSSPropertyID::kRight: + return true; + default: + break; } return false; } +bool ComputedStyle::HasWillChangeCompositingHint() const { + const auto& properties = WillChangeProperties(); + return std::any_of(properties.begin(), properties.end(), + IsWillChangeCompositingHintProperty); +} + +bool ComputedStyle::HasWillChangeTransformHint() const { + const auto& properties = WillChangeProperties(); + return std::any_of(properties.begin(), properties.end(), + IsWillChangeTransformHintProperty); +} + bool ComputedStyle::RequireTransformOrigin( ApplyTransformOrigin apply_origin, ApplyMotionPath apply_motion_path) const {
diff --git a/third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.cc b/third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.cc index f514d9efe..f704944 100644 --- a/third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.cc +++ b/third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.cc
@@ -30,6 +30,7 @@ #include "third_party/blink/renderer/platform/graphics/filters/paint_filter_effect.h" #include "third_party/blink/renderer/platform/graphics/filters/source_alpha.h" #include "third_party/blink/renderer/platform/graphics/filters/source_graphic.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -113,18 +114,19 @@ FilterEffect* source_graphic_ref = source_graphic; builtin_effects_.insert(FilterInputKeywords::GetSourceGraphic(), source_graphic_ref); - builtin_effects_.insert(FilterInputKeywords::SourceAlpha(), - SourceAlpha::Create(source_graphic_ref)); + builtin_effects_.insert( + FilterInputKeywords::SourceAlpha(), + MakeGarbageCollected<SourceAlpha>(source_graphic_ref)); if (fill_flags) { builtin_effects_.insert(FilterInputKeywords::FillPaint(), - PaintFilterEffect::Create( + MakeGarbageCollected<PaintFilterEffect>( source_graphic_ref->GetFilter(), *fill_flags)); } if (stroke_flags) { builtin_effects_.insert( FilterInputKeywords::StrokePaint(), - PaintFilterEffect::Create(source_graphic_ref->GetFilter(), - *stroke_flags)); + MakeGarbageCollected<PaintFilterEffect>(source_graphic_ref->GetFilter(), + *stroke_flags)); } AddBuiltinEffects(); }
diff --git a/third_party/blink/renderer/core/svg/svg_fe_blend_element.cc b/third_party/blink/renderer/core/svg/svg_fe_blend_element.cc index fba813e9..6560309 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_blend_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_blend_element.cc
@@ -24,6 +24,7 @@ #include "third_party/blink/renderer/core/svg/svg_enumeration_map.h" #include "third_party/blink/renderer/core/svg_names.h" #include "third_party/blink/renderer/platform/graphics/filters/fe_blend.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -138,8 +139,8 @@ DCHECK(input1); DCHECK(input2); - FilterEffect* effect = - FEBlend::Create(filter, ToBlendMode(mode_->CurrentValue()->EnumValue())); + auto* effect = MakeGarbageCollected<FEBlend>( + filter, ToBlendMode(mode_->CurrentValue()->EnumValue())); FilterEffectVector& input_effects = effect->InputEffects(); input_effects.ReserveCapacity(2); input_effects.push_back(input1);
diff --git a/third_party/blink/renderer/core/svg/svg_fe_color_matrix_element.cc b/third_party/blink/renderer/core/svg/svg_fe_color_matrix_element.cc index 07d47ab0..2e715d6 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_color_matrix_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_color_matrix_element.cc
@@ -23,6 +23,7 @@ #include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h" #include "third_party/blink/renderer/core/svg/svg_enumeration_map.h" #include "third_party/blink/renderer/core/svg_names.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -100,8 +101,8 @@ ColorMatrixType filter_type = type_->CurrentValue()->EnumValue(); Vector<float> filter_values = values_->CurrentValue()->ToFloatVector(); - FilterEffect* effect = - FEColorMatrix::Create(filter, filter_type, filter_values); + auto* effect = + MakeGarbageCollected<FEColorMatrix>(filter, filter_type, filter_values); effect->InputEffects().push_back(input1); return effect; }
diff --git a/third_party/blink/renderer/core/svg/svg_fe_component_transfer_element.cc b/third_party/blink/renderer/core/svg/svg_fe_component_transfer_element.cc index 6255f1e..ab0bec7 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_component_transfer_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_component_transfer_element.cc
@@ -28,6 +28,7 @@ #include "third_party/blink/renderer/core/svg/svg_fe_func_r_element.h" #include "third_party/blink/renderer/core/svg_names.h" #include "third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -81,8 +82,8 @@ alpha = func_a->TransferFunction(); } - FilterEffect* effect = - FEComponentTransfer::Create(filter, red, green, blue, alpha); + auto* effect = MakeGarbageCollected<FEComponentTransfer>(filter, red, green, + blue, alpha); effect->InputEffects().push_back(input1); return effect; }
diff --git a/third_party/blink/renderer/core/svg/svg_fe_composite_element.cc b/third_party/blink/renderer/core/svg/svg_fe_composite_element.cc index 68c63e647..ac7e5e6 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_composite_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_composite_element.cc
@@ -23,6 +23,7 @@ #include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h" #include "third_party/blink/renderer/core/svg/svg_enumeration_map.h" #include "third_party/blink/renderer/core/svg_names.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -124,7 +125,7 @@ DCHECK(input1); DCHECK(input2); - FilterEffect* effect = FEComposite::Create( + auto* effect = MakeGarbageCollected<FEComposite>( filter, svg_operator_->CurrentValue()->EnumValue(), k1_->CurrentValue()->Value(), k2_->CurrentValue()->Value(), k3_->CurrentValue()->Value(), k4_->CurrentValue()->Value());
diff --git a/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.cc b/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.cc index e699329..3b4cc6c 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.cc
@@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/svg_names.h" #include "third_party/blink/renderer/platform/geometry/int_point.h" #include "third_party/blink/renderer/platform/geometry/int_size.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -206,7 +207,7 @@ AtomicString(in1_->CurrentValue()->Value())); DCHECK(input1); - FilterEffect* effect = FEConvolveMatrix::Create( + auto* effect = MakeGarbageCollected<FEConvolveMatrix>( filter, MatrixOrder(), ComputeDivisor(), bias_->CurrentValue()->Value(), TargetPoint(), edge_mode_->CurrentValue()->EnumValue(), preserve_alpha_->CurrentValue()->Value(),
diff --git a/third_party/blink/renderer/core/svg/svg_fe_diffuse_lighting_element.cc b/third_party/blink/renderer/core/svg/svg_fe_diffuse_lighting_element.cc index 85e8226..427b5f5af 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_diffuse_lighting_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_diffuse_lighting_element.cc
@@ -24,6 +24,7 @@ #include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h" #include "third_party/blink/renderer/platform/graphics/filters/fe_diffuse_lighting.h" #include "third_party/blink/renderer/platform/graphics/filters/filter.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -154,7 +155,7 @@ scoped_refptr<LightSource> light_source = light_node ? light_node->GetLightSource(filter) : nullptr; - FilterEffect* effect = FEDiffuseLighting::Create( + auto* effect = MakeGarbageCollected<FEDiffuseLighting>( filter, color, surface_scale_->CurrentValue()->Value(), diffuse_constant_->CurrentValue()->Value(), std::move(light_source)); effect->InputEffects().push_back(input1);
diff --git a/third_party/blink/renderer/core/svg/svg_fe_displacement_map_element.cc b/third_party/blink/renderer/core/svg/svg_fe_displacement_map_element.cc index 9ae2ddd..50fcd40 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_displacement_map_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_displacement_map_element.cc
@@ -22,6 +22,7 @@ #include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h" #include "third_party/blink/renderer/core/svg/svg_enumeration_map.h" #include "third_party/blink/renderer/core/svg_names.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -113,7 +114,7 @@ DCHECK(input1); DCHECK(input2); - FilterEffect* effect = FEDisplacementMap::Create( + auto* effect = MakeGarbageCollected<FEDisplacementMap>( filter, x_channel_selector_->CurrentValue()->EnumValue(), y_channel_selector_->CurrentValue()->EnumValue(), scale_->CurrentValue()->Value());
diff --git a/third_party/blink/renderer/core/svg/svg_fe_drop_shadow_element.cc b/third_party/blink/renderer/core/svg/svg_fe_drop_shadow_element.cc index bc187c9..11481e0 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_drop_shadow_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_drop_shadow_element.cc
@@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h" #include "third_party/blink/renderer/core/svg_names.h" #include "third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -108,7 +109,7 @@ // Clamp std.dev. to non-negative. (See SVGFEGaussianBlurElement::build) float std_dev_x = std::max(0.0f, stdDeviationX()->CurrentValue()->Value()); float std_dev_y = std::max(0.0f, stdDeviationY()->CurrentValue()->Value()); - FilterEffect* effect = FEDropShadow::Create( + auto* effect = MakeGarbageCollected<FEDropShadow>( filter, std_dev_x, std_dev_y, dx_->CurrentValue()->Value(), dy_->CurrentValue()->Value(), color, opacity); effect->InputEffects().push_back(input1);
diff --git a/third_party/blink/renderer/core/svg/svg_fe_flood_element.cc b/third_party/blink/renderer/core/svg/svg_fe_flood_element.cc index 3ea9634..d0ae516 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_flood_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_flood_element.cc
@@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/style/svg_computed_style.h" #include "third_party/blink/renderer/core/svg_names.h" #include "third_party/blink/renderer/platform/graphics/filters/fe_flood.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -58,7 +59,7 @@ Color color = style->VisitedDependentColor(GetCSSPropertyFloodColor()); float opacity = style->SvgStyle().FloodOpacity(); - return FEFlood::Create(filter, color, opacity); + return MakeGarbageCollected<FEFlood>(filter, color, opacity); } bool SVGFEFloodElement::TaintsOrigin() const {
diff --git a/third_party/blink/renderer/core/svg/svg_fe_gaussian_blur_element.cc b/third_party/blink/renderer/core/svg/svg_fe_gaussian_blur_element.cc index 6bee7ec..051c741 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_gaussian_blur_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_gaussian_blur_element.cc
@@ -23,6 +23,7 @@ #include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h" #include "third_party/blink/renderer/core/svg_names.h" #include "third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -77,7 +78,8 @@ // => Clamp to non-negative. float std_dev_x = std::max(0.0f, stdDeviationX()->CurrentValue()->Value()); float std_dev_y = std::max(0.0f, stdDeviationY()->CurrentValue()->Value()); - FilterEffect* effect = FEGaussianBlur::Create(filter, std_dev_x, std_dev_y); + auto* effect = + MakeGarbageCollected<FEGaussianBlur>(filter, std_dev_x, std_dev_y); effect->InputEffects().push_back(input1); return effect; }
diff --git a/third_party/blink/renderer/core/svg/svg_fe_merge_element.cc b/third_party/blink/renderer/core/svg/svg_fe_merge_element.cc index 8c1565d..cebb72f 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_merge_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_merge_element.cc
@@ -35,7 +35,7 @@ FilterEffect* SVGFEMergeElement::Build(SVGFilterBuilder* filter_builder, Filter* filter) { - FilterEffect* effect = FEMerge::Create(filter); + FilterEffect* effect = MakeGarbageCollected<FEMerge>(filter); FilterEffectVector& merge_inputs = effect->InputEffects(); for (SVGFEMergeNodeElement& merge_node : Traversal<SVGFEMergeNodeElement>::ChildrenOf(*this)) {
diff --git a/third_party/blink/renderer/core/svg/svg_fe_morphology_element.cc b/third_party/blink/renderer/core/svg/svg_fe_morphology_element.cc index 15e75d0..f1989a3 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_morphology_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_morphology_element.cc
@@ -22,6 +22,7 @@ #include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h" #include "third_party/blink/renderer/core/svg/svg_enumeration_map.h" #include "third_party/blink/renderer/core/svg_names.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -112,7 +113,7 @@ // (This is handled by FEMorphology) float x_radius = radiusX()->CurrentValue()->Value(); float y_radius = radiusY()->CurrentValue()->Value(); - FilterEffect* effect = FEMorphology::Create( + auto* effect = MakeGarbageCollected<FEMorphology>( filter, svg_operator_->CurrentValue()->EnumValue(), x_radius, y_radius); effect->InputEffects().push_back(input1); return effect;
diff --git a/third_party/blink/renderer/core/svg/svg_fe_offset_element.cc b/third_party/blink/renderer/core/svg/svg_fe_offset_element.cc index 349fc64..bca8ea0 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_offset_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_offset_element.cc
@@ -23,6 +23,7 @@ #include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h" #include "third_party/blink/renderer/core/svg_names.h" #include "third_party/blink/renderer/platform/graphics/filters/fe_offset.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -62,8 +63,8 @@ AtomicString(in1_->CurrentValue()->Value())); DCHECK(input1); - FilterEffect* effect = FEOffset::Create(filter, dx_->CurrentValue()->Value(), - dy_->CurrentValue()->Value()); + auto* effect = MakeGarbageCollected<FEOffset>( + filter, dx_->CurrentValue()->Value(), dy_->CurrentValue()->Value()); effect->InputEffects().push_back(input1); return effect; }
diff --git a/third_party/blink/renderer/core/svg/svg_fe_specular_lighting_element.cc b/third_party/blink/renderer/core/svg/svg_fe_specular_lighting_element.cc index e077742..ebc2b3b 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_specular_lighting_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_specular_lighting_element.cc
@@ -26,6 +26,7 @@ #include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h" #include "third_party/blink/renderer/platform/graphics/filters/fe_specular_lighting.h" #include "third_party/blink/renderer/platform/graphics/filters/filter.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -164,7 +165,7 @@ scoped_refptr<LightSource> light_source = light_node ? light_node->GetLightSource(filter) : nullptr; - FilterEffect* effect = FESpecularLighting::Create( + auto* effect = MakeGarbageCollected<FESpecularLighting>( filter, color, surface_scale_->CurrentValue()->Value(), specular_constant_->CurrentValue()->Value(), specular_exponent_->CurrentValue()->Value(), std::move(light_source));
diff --git a/third_party/blink/renderer/core/svg/svg_fe_tile_element.cc b/third_party/blink/renderer/core/svg/svg_fe_tile_element.cc index aa39c46..e708a27 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_tile_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_tile_element.cc
@@ -23,6 +23,7 @@ #include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h" #include "third_party/blink/renderer/core/svg_names.h" #include "third_party/blink/renderer/platform/graphics/filters/fe_tile.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -55,7 +56,7 @@ AtomicString(in1_->CurrentValue()->Value())); DCHECK(input1); - FilterEffect* effect = FETile::Create(filter); + auto* effect = MakeGarbageCollected<FETile>(filter); effect->InputEffects().push_back(input1); return effect; }
diff --git a/third_party/blink/renderer/core/svg/svg_fe_turbulence_element.cc b/third_party/blink/renderer/core/svg/svg_fe_turbulence_element.cc index 091ce66..7f328bfc 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_turbulence_element.cc +++ b/third_party/blink/renderer/core/svg/svg_fe_turbulence_element.cc
@@ -22,6 +22,7 @@ #include "third_party/blink/renderer/core/svg/svg_enumeration_map.h" #include "third_party/blink/renderer/core/svg_names.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -121,7 +122,7 @@ } FilterEffect* SVGFETurbulenceElement::Build(SVGFilterBuilder*, Filter* filter) { - return FETurbulence::Create( + return MakeGarbageCollected<FETurbulence>( filter, type_->CurrentValue()->EnumValue(), baseFrequencyX()->CurrentValue()->Value(), baseFrequencyY()->CurrentValue()->Value(),
diff --git a/third_party/blink/renderer/devtools/front_end/Runtime.js b/third_party/blink/renderer/devtools/front_end/Runtime.js index 46698e7..28cb0dc 100644 --- a/third_party/blink/renderer/devtools/front_end/Runtime.js +++ b/third_party/blink/renderer/devtools/front_end/Runtime.js
@@ -549,8 +549,9 @@ } /** - * @param {!Function} constructorFunction - * @return {!Object} + * @param {function(new:T)} constructorFunction + * @return {!T} + * @template T */ sharedInstance(constructorFunction) { if (Runtime._instanceSymbol in constructorFunction &&
diff --git a/third_party/blink/renderer/devtools/front_end/perf_ui/LineLevelProfile.js b/third_party/blink/renderer/devtools/front_end/perf_ui/LineLevelProfile.js index 8e88d14..5611239 100644 --- a/third_party/blink/renderer/devtools/front_end/perf_ui/LineLevelProfile.js +++ b/third_party/blink/renderer/devtools/front_end/perf_ui/LineLevelProfile.js
@@ -60,15 +60,6 @@ } this._helper.scheduleUpdate(); } - - /** - * @return {!PerfUI.LineLevelProfile.Performance} - */ - static instance() { - if (!PerfUI.LineLevelProfile.Performance._instance) - PerfUI.LineLevelProfile.Performance._instance = new PerfUI.LineLevelProfile.Performance(); - return PerfUI.LineLevelProfile.Performance._instance; - } }; PerfUI.LineLevelProfile.Memory = class { @@ -103,15 +94,6 @@ helper.addLineData(target, script, line, node.selfSize); } } - - /** - * @return {!PerfUI.LineLevelProfile.Memory} - */ - static instance() { - if (!PerfUI.LineLevelProfile.Memory._instance) - PerfUI.LineLevelProfile.Memory._instance = new PerfUI.LineLevelProfile.Memory(); - return PerfUI.LineLevelProfile.Memory._instance; - } }; PerfUI.LineLevelProfile._Helper = class {
diff --git a/third_party/blink/renderer/devtools/front_end/perf_ui/LiveHeapProfile.js b/third_party/blink/renderer/devtools/front_end/perf_ui/LiveHeapProfile.js index e8b74a7..ed94316d 100644 --- a/third_party/blink/renderer/devtools/front_end/perf_ui/LiveHeapProfile.js +++ b/third_party/blink/renderer/devtools/front_end/perf_ui/LiveHeapProfile.js
@@ -50,7 +50,7 @@ async onUpdateProfiles() { const models = SDK.targetManager.models(SDK.HeapProfilerModel); const profiles = await Promise.all(models.map(model => model.getSamplingProfile())); - const lineLevelProfile = PerfUI.LineLevelProfile.Memory.instance(); + const lineLevelProfile = self.runtime.sharedInstance(PerfUI.LineLevelProfile.Memory); lineLevelProfile.reset(); for (let i = 0; i < profiles.length; ++i) { if (profiles[i])
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileView.js b/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileView.js index 8157ccd..5ed69064 100644 --- a/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileView.js +++ b/third_party/blink/renderer/devtools/front_end/profiler/CPUProfileView.js
@@ -46,7 +46,7 @@ */ wasShown() { super.wasShown(); - const lineLevelProfile = PerfUI.LineLevelProfile.Performance.instance(); + const lineLevelProfile = self.runtime.sharedInstance(PerfUI.LineLevelProfile.Performance); lineLevelProfile.reset(); lineLevelProfile.appendCPUProfile(this._profileHeader.profileModel()); }
diff --git a/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js b/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js index cfaf9de..c9b1471 100644 --- a/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js +++ b/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js
@@ -40,9 +40,27 @@ this._toolbar = new UI.Toolbar('background-service-toolbar', this.contentElement); this._setupToolbar(); + /** + * This will contain the DataGrid for displaying events, and a panel at the bottom for showing + * extra metadata related to the selected event. + * @const {!UI.SplitWidget} + */ + this._splitWidget = new UI.SplitWidget(/* isVertical= */ false, /* secondIsSidebar= */ true); + this._splitWidget.show(this.contentElement); + /** @const {!DataGrid.DataGrid} */ this._dataGrid = this._createDataGrid(); - this._dataGrid.asWidget().show(this.contentElement); + + /** @const {!UI.VBox} */ + this._previewPanel = new UI.VBox(); + + /** @type {?UI.Widget} */ + this._preview = null; + + this._splitWidget.setMainWidget(this._dataGrid.asWidget()); + this._splitWidget.setSidebarWidget(this._previewPanel); + + this._showPreview(null); } /** @@ -55,28 +73,36 @@ this._recordButton.setToggleWithRedColor(true); this._toolbar.appendToolbarItem(this._recordButton); - const refreshButton = new UI.ToolbarButton(Common.UIString('Refresh'), 'largeicon-refresh'); - refreshButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._refreshView()); - this._toolbar.appendToolbarItem(refreshButton); - const clearButton = new UI.ToolbarButton(Common.UIString('Clear'), 'largeicon-clear'); - clearButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._clearView()); + clearButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._clearEvents()); this._toolbar.appendToolbarItem(clearButton); this._toolbar.appendSeparator(); - const deleteButton = new UI.ToolbarButton(Common.UIString('Delete'), 'largeicon-trash-bin'); - deleteButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._deleteEvents()); - this._toolbar.appendToolbarItem(deleteButton); - - this._toolbar.appendSeparator(); - this._originCheckbox = new UI.ToolbarCheckbox(Common.UIString('Show events from other domains'), undefined, () => this._refreshView()); this._toolbar.appendToolbarItem(this._originCheckbox); } /** + * Displays all available events in the grid. + */ + _refreshView() { + this._clearView(); + const events = this._model.getEvents(this._serviceName).filter(event => this._acceptEvent(event)); + for (const event of events) + this._addEvent(event); + } + + /** + * Clears the grid and panel. + */ + _clearView() { + this._dataGrid.rootNode().removeChildren(); + this._showPreview(null); + } + + /** * Called when the `Toggle Record` button is clicked. */ _toggleRecording() { @@ -84,26 +110,9 @@ } /** - * Called when the `Refresh` button is clicked. - */ - _refreshView() { - this._clearView(); - const events = this._model.getEvents(this._serviceName).filter(event => this._acceptEvent(event)); - for (const event of events) - this._addEvent(event); - } - - /** * Called when the `Clear` button is clicked. */ - _clearView() { - this._dataGrid.rootNode().removeChildren(); - } - - /** - * Called when the `Delete` button is clicked. - */ - _deleteEvents() { + _clearEvents() { this._model.clearEvents(this._serviceName); this._clearView(); } @@ -158,6 +167,11 @@ ]); const dataGrid = new DataGrid.DataGrid(columns); dataGrid.setStriped(true); + + dataGrid.addEventListener( + DataGrid.DataGrid.Events.SelectedNode, + event => this._showPreview(/** @type {!Resources.BackgroundServiceView.EventDataNode} */ (event.data))); + return dataGrid; } @@ -205,6 +219,21 @@ return this._securityOriginManager.securityOrigins().includes(origin); } + + /** + * @param {?Resources.BackgroundServiceView.EventDataNode} dataNode + */ + _showPreview(dataNode) { + if (this._preview) + this._preview.detach(); + + if (dataNode) + this._preview = dataNode.createPreview(); + else + this._preview = new UI.EmptyWidget(ls`Select a value to preview`); + + this._preview.show(this._previewPanel.contentElement); + } }; /** @@ -229,60 +258,15 @@ /** @const {!Array<!Protocol.BackgroundService.EventMetadata>} */ this._eventMetadata = eventMetadata; - - /** @type {?UI.PopoverHelper} */ - this._popoverHelper = null; } /** - * @override - * @return {!Element} + * @return {!UI.SearchableView} */ - createElement() { - const element = super.createElement(); - - this._popoverHelper = new UI.PopoverHelper(element, event => this._createPopover(event)); - this._popoverHelper.setHasPadding(true); - this._popoverHelper.setTimeout(300, 300); - - return element; - } - - /** - * @param {!Event} event - * @return {?UI.PopoverRequest} - */ - _createPopover(event) { - if (event.type !== 'mousedown') - return null; - - // Create popover container. - const container = createElementWithClass('div', 'background-service-popover-container'); - UI.appendStyle(container, 'resources/backgroundServiceView.css'); - - if (!this._eventMetadata.length) { - const entryDiv = createElementWithClass('div', 'background-service-metadata-entry'); - entryDiv.textContent = 'There is no metadata for this event'; - container.appendChild(entryDiv); - } - - for (const entry of this._eventMetadata) { - const entryDiv = createElementWithClass('div', 'background-service-metadata-entry'); - const key = createElementWithClass('label', 'background-service-metadata-key'); - key.textContent = `${entry.key}: `; - const value = createElementWithClass('label', 'background-service-metadata-value'); - value.textContent = entry.value; - entryDiv.appendChild(key); - entryDiv.appendChild(value); - container.appendChild(entryDiv); - } - - return { - box: event.target.boxInWindow(), - show: popover => { - popover.contentElement.appendChild(container); - return Promise.resolve(true); - }, - }; + createPreview() { + const metadata = {}; + for (const entry of this._eventMetadata) + metadata[entry.key] = entry.value; + return SourceFrame.JSONView.createViewSync(metadata); } };
diff --git a/third_party/blink/renderer/devtools/front_end/resources/backgroundServiceView.css b/third_party/blink/renderer/devtools/front_end/resources/backgroundServiceView.css index 356e4fc..c276c7a6 100644 --- a/third_party/blink/renderer/devtools/front_end/resources/backgroundServiceView.css +++ b/third_party/blink/renderer/devtools/front_end/resources/backgroundServiceView.css
@@ -5,20 +5,5 @@ .data-grid { flex: auto; -} - -.background-service-popover-container { - padding: 12px 16px 0px 16px; -} - -.background-service-metadata-entry { - margin-bottom: 12px; -} - -.background-service-metadata-key { - font-weight: bold; -} - -.background-service-metadata-value { - font-family: monospace; + border: none; }
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js b/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js index bd70c6a..6919fa7 100644 --- a/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js +++ b/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js
@@ -12,6 +12,7 @@ this._heapProfilerAgent = target.heapProfilerAgent(); this._memoryAgent = target.memoryAgent(); this._runtimeModel = /** @type {!SDK.RuntimeModel} */ (target.model(SDK.RuntimeModel)); + this._samplingProfilerDepth = 0; } /** @@ -40,6 +41,8 @@ * @param {number=} samplingRateInBytes */ startSampling(samplingRateInBytes) { + if (this._samplingProfilerDepth++) + return; const defaultSamplingIntervalInBytes = 16384; this._heapProfilerAgent.startSampling(samplingRateInBytes || defaultSamplingIntervalInBytes); } @@ -48,6 +51,10 @@ * @return {!Promise<?Protocol.HeapProfiler.SamplingHeapProfile>} */ stopSampling() { + if (!this._samplingProfilerDepth) + throw new Error('Sampling profiler is not running.'); + if (--this._samplingProfilerDepth) + return this.getSamplingProfile(); return this._heapProfilerAgent.stopSampling(); }
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js b/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js index 46e4019..a944356 100644 --- a/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js +++ b/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js
@@ -549,7 +549,7 @@ } _reset() { - PerfUI.LineLevelProfile.Performance.instance().reset(); + self.runtime.sharedInstance(PerfUI.LineLevelProfile.Performance).reset(); this._setModel(null); } @@ -582,7 +582,7 @@ Timeline.PerformanceModel.Events.WindowChanged, this._onModelWindowChanged, this); this._overviewPane.setBounds( model.timelineModel().minimumRecordTime(), model.timelineModel().maximumRecordTime()); - const lineLevelProfile = PerfUI.LineLevelProfile.Performance.instance(); + const lineLevelProfile = self.runtime.sharedInstance(PerfUI.LineLevelProfile.Performance); lineLevelProfile.reset(); for (const profile of model.timelineModel().cpuProfiles()) lineLevelProfile.appendCPUProfile(profile);
diff --git a/third_party/blink/renderer/modules/media_controls/BUILD.gn b/third_party/blink/renderer/modules/media_controls/BUILD.gn index d981bac..600a477 100644 --- a/third_party/blink/renderer/modules/media_controls/BUILD.gn +++ b/third_party/blink/renderer/modules/media_controls/BUILD.gn
@@ -92,6 +92,8 @@ "media_controls_resource_loader.h", "media_controls_rotate_to_fullscreen_delegate.cc", "media_controls_rotate_to_fullscreen_delegate.h", + "media_controls_shared_helper.cc", + "media_controls_shared_helper.h", "media_controls_text_track_manager.cc", "media_controls_text_track_manager.h", ] @@ -111,6 +113,8 @@ "touchless/elements/media_controls_touchless_play_button_element.h", "touchless/elements/media_controls_touchless_seek_button_element.cc", "touchless/elements/media_controls_touchless_seek_button_element.h", + "touchless/elements/media_controls_touchless_timeline_element.cc", + "touchless/elements/media_controls_touchless_timeline_element.h", "touchless/elements/media_controls_touchless_volume_button_element.cc", "touchless/elements/media_controls_touchless_volume_button_element.h", "touchless/media_controls_touchless_impl.cc",
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.cc index ce16173..e2c07153 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.cc
@@ -29,11 +29,11 @@ #include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h" #include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h" #include "third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.h" +#include "third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace { -const double kCurrentTimeBufferedDelta = 1.0; const int kThumbRadius = 6; // Only respond to main button of primary pointer(s). @@ -219,22 +219,14 @@ if (MediaControlsImpl::IsModern()) before_segment.width = current_position; - // Calculate the size of the after segment (i.e. what has been buffered). - for (unsigned i = 0; i < buffered_time_ranges->length(); ++i) { - float start = buffered_time_ranges->start(i, ASSERT_NO_EXCEPTION); - float end = buffered_time_ranges->end(i, ASSERT_NO_EXCEPTION); - // The delta is there to avoid corner cases when buffered - // ranges is out of sync with current time because of - // asynchronous media pipeline and current time caching in - // HTMLMediaElement. - // This is related to https://www.w3.org/Bugs/Public/show_bug.cgi?id=28125 - // FIXME: Remove this workaround when WebMediaPlayer - // has an asynchronous pause interface. - if (std::isnan(start) || std::isnan(end) || - start > current_time + kCurrentTimeBufferedDelta || - end < current_time) { - continue; - } + base::Optional<unsigned> current_buffered_time_range = + MediaControlsSharedHelpers::GetCurrentBufferedTimeRange(MediaElement()); + + if (current_buffered_time_range) { + float start = buffered_time_ranges->start( + current_buffered_time_range.value(), ASSERT_NO_EXCEPTION); + float end = buffered_time_ranges->end(current_buffered_time_range.value(), + ASSERT_NO_EXCEPTION); double start_position = start / duration; double end_position = end / duration; @@ -256,10 +248,6 @@ before_segment.width = end_position - current_position; } } - - // Break out of the loop since we've drawn the only buffered range - // we're going to draw. - break; } // Update the positions of the segments.
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.cc b/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.cc new file mode 100644 index 0000000..9071fdf --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.cc
@@ -0,0 +1,55 @@ +// 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/media_controls/media_controls_shared_helper.h" + +#include <cmath> +#include "third_party/blink/renderer/core/html/media/html_media_element.h" +#include "third_party/blink/renderer/core/html/time_ranges.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" + +namespace { + +const double kCurrentTimeBufferedDelta = 1.0; + +} + +namespace blink { + +base::Optional<unsigned> +MediaControlsSharedHelpers::GetCurrentBufferedTimeRange( + HTMLMediaElement& media_element) { + double current_time = media_element.currentTime(); + double duration = media_element.duration(); + TimeRanges* buffered_time_ranges = media_element.buffered(); + + DCHECK(buffered_time_ranges); + + if (std::isnan(duration) || std::isinf(duration) || !duration || + std::isnan(current_time)) { + return base::nullopt; + } + + // Calculate the size of the after segment (i.e. what has been buffered). + for (unsigned i = 0; i < buffered_time_ranges->length(); ++i) { + float start = buffered_time_ranges->start(i, ASSERT_NO_EXCEPTION); + float end = buffered_time_ranges->end(i, ASSERT_NO_EXCEPTION); + // The delta is there to avoid corner cases when buffered + // ranges is out of sync with current time because of + // asynchronous media pipeline and current time caching in + // HTMLMediaElement. + // This is related to https://www.w3.org/Bugs/Public/show_bug.cgi?id=28125 + // FIXME: Remove this workaround when WebMediaPlayer + // has an asynchronous pause interface. + if (!std::isnan(start) && !std::isnan(end) && + start <= current_time + kCurrentTimeBufferedDelta && + end > current_time) { + return i; + } + } + + return base::nullopt; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.h b/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.h new file mode 100644 index 0000000..d8a3e97c --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.h
@@ -0,0 +1,25 @@ +// 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_MEDIA_CONTROLS_MEDIA_CONTROLS_SHARED_HELPER_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_MEDIA_CONTROLS_SHARED_HELPER_H_ + +#include "base/optional.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" + +namespace blink { + +class HTMLMediaElement; + +class MediaControlsSharedHelpers final { + STATIC_ONLY(MediaControlsSharedHelpers); + + public: + static base::Optional<unsigned> GetCurrentBufferedTimeRange( + HTMLMediaElement& media_element); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_MEDIA_CONTROLS_SHARED_HELPER_H_
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.cc b/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.cc index 22c5801d..e6142888 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.cc +++ b/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.cc
@@ -15,6 +15,10 @@ media_controls_->MediaEventListener().AddObserver(this); } +HTMLMediaElement& MediaControlsTouchlessElement::MediaElement() const { + return media_controls_->MediaElement(); +} + void MediaControlsTouchlessElement::Trace(blink::Visitor* visitor) { visitor->Trace(media_controls_); }
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h b/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h index e4509ac..0785f485 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h +++ b/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h
@@ -11,17 +11,21 @@ namespace blink { +class HTMLMediaElement; class MediaControlsTouchlessImpl; class MediaControlsTouchlessElement : public MediaControlsTouchlessMediaEventListenerObserver { public: + HTMLMediaElement& MediaElement() const; + void Trace(blink::Visitor* visitor) override; // Non-touch media event listener observer implementation. void OnFocusIn() override {} void OnTimeUpdate() override {} void OnDurationChange() override {} + void OnLoadingProgress() override {} void OnPlay() override {} void OnPause() override {} void OnError() override {}
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.cc b/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.cc new file mode 100644 index 0000000..e06998a --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.cc
@@ -0,0 +1,95 @@ +// 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/media_controls/touchless/elements/media_controls_touchless_timeline_element.h" + +#include "third_party/blink/renderer/core/html/media/html_media_element.h" +#include "third_party/blink/renderer/core/html/time_ranges.h" +#include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h" +#include "third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.h" +#include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h" +#include "third_party/blink/renderer/platform/wtf/text/string_builder.h" + +namespace blink { + +MediaControlsTouchlessTimelineElement::MediaControlsTouchlessTimelineElement( + MediaControlsTouchlessImpl& media_controls) + : HTMLDivElement(media_controls.GetDocument()), + MediaControlsTouchlessElement(media_controls) { + SetShadowPseudoId( + AtomicString("-internal-media-controls-touchless-timeline")); + + loaded_bar_ = MediaControlElementsHelper::CreateDiv( + "-internal-media-controls-touchless-timeline-loaded", this); + progress_bar_ = MediaControlElementsHelper::CreateDiv( + "-internal-media-controls-touchless-timeline-progress", loaded_bar_); +} + +void MediaControlsTouchlessTimelineElement::OnLoadingProgress() { + UpdateBarsCSS(); +} + +void MediaControlsTouchlessTimelineElement::OnTimeUpdate() { + current_time_ = MediaElement().currentTime(); + UpdateBars(); +} + +void MediaControlsTouchlessTimelineElement::OnDurationChange() { + duration_ = MediaElement().duration(); + UpdateBars(); +} + +void MediaControlsTouchlessTimelineElement::UpdateBars() { + if (std::isnan(duration_) || std::isinf(duration_) || !duration_ || + std::isnan(current_time_)) { + progress_percent_ = 0; + loaded_percent_ = 0; + UpdateBarsCSS(); + return; + } + + progress_percent_ = current_time_ / duration_; + loaded_percent_ = progress_percent_; + + base::Optional<unsigned> current_buffered_time_range = + MediaControlsSharedHelpers::GetCurrentBufferedTimeRange(MediaElement()); + if (current_buffered_time_range) { + TimeRanges* buffered_time_ranges = MediaElement().buffered(); + float end = buffered_time_ranges->end(current_buffered_time_range.value(), + ASSERT_NO_EXCEPTION); + loaded_percent_ = end / duration_; + } + + UpdateBarsCSS(); +} + +void MediaControlsTouchlessTimelineElement::UpdateBarsCSS() { + SetBarWidth(loaded_bar_, loaded_percent_); + + // Since progress bar is a child of loaded bar, we need to calculate + // the percentage accordingly. + double adjusted_width_percent = 0; + if (loaded_percent_ != 0) + adjusted_width_percent = progress_percent_ / loaded_percent_; + + SetBarWidth(progress_bar_, adjusted_width_percent); +} + +void MediaControlsTouchlessTimelineElement::SetBarWidth(HTMLDivElement* bar, + double percent) { + StringBuilder builder; + builder.Append("width:"); + builder.AppendNumber(percent * 100); + builder.Append("%"); + bar->setAttribute("style", builder.ToAtomicString()); +} + +void MediaControlsTouchlessTimelineElement::Trace(blink::Visitor* visitor) { + visitor->Trace(loaded_bar_); + visitor->Trace(progress_bar_); + HTMLDivElement::Trace(visitor); + MediaControlsTouchlessElement::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.h b/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.h new file mode 100644 index 0000000..0050fcf --- /dev/null +++ b/third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.h
@@ -0,0 +1,47 @@ +// 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_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_TIMELINE_ELEMENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_TIMELINE_ELEMENT_H_ + +#include "third_party/blink/renderer/core/html/html_div_element.h" +#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_element.h" + +namespace blink { + +class MediaControlsTouchlessTimelineElement + : public HTMLDivElement, + public MediaControlsTouchlessElement { + USING_GARBAGE_COLLECTED_MIXIN(MediaControlsTouchlessTimelineElement); + + public: + explicit MediaControlsTouchlessTimelineElement(MediaControlsTouchlessImpl&); + + // MediaControlsTouchlessMediaEventListenerObserver overrides + void OnTimeUpdate() override; + void OnDurationChange() override; + void OnLoadingProgress() override; + + void Trace(blink::Visitor*) override; + + private: + void SetBarWidth(HTMLDivElement* bar, double percent); + + void UpdateBars(); + void UpdateBarsCSS(); + + Member<HTMLDivElement> loaded_bar_; + Member<HTMLDivElement> progress_bar_; + double current_time_; + double duration_; + + // Used for setting the width of the progress and loaded bars. This is + // a percentage of the duration of the media. + double progress_percent_; + double loaded_percent_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_TOUCHLESS_ELEMENTS_MEDIA_CONTROLS_TOUCHLESS_TIMELINE_ELEMENT_H_
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.cc b/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.cc index 94d034c..4b97be0 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.cc +++ b/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.cc
@@ -22,6 +22,7 @@ #include "third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.h" #include "third_party/blink/renderer/modules/media_controls/media_controls_text_track_manager.h" #include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_overlay_element.h" +#include "third_party/blink/renderer/modules/media_controls/touchless/elements/media_controls_touchless_timeline_element.h" #include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.h" #include "third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_resource_loader.h" #include "third_party/blink/renderer/platform/keyboard_codes.h" @@ -80,8 +81,11 @@ MakeGarbageCollected<MediaControlsTouchlessImpl>(media_element); MediaControlsTouchlessOverlayElement* overlay_element = MakeGarbageCollected<MediaControlsTouchlessOverlayElement>(*controls); + MediaControlsTouchlessTimelineElement* timeline_element = + MakeGarbageCollected<MediaControlsTouchlessTimelineElement>(*controls); controls->ParserAppendChild(overlay_element); + controls->ParserAppendChild(timeline_element); // Controls start hidden. controls->MakeTransparent();
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h b/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h index a893d0f3..bcb6d391 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h +++ b/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl.h
@@ -53,6 +53,7 @@ void OnFocusIn() override; void OnTimeUpdate() override {} void OnDurationChange() override {} + void OnLoadingProgress() override {} void OnPlay() override {} void OnPause() override {} void OnError() override {}
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl_test.cc b/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl_test.cc index 7007591..8d5c1f1b 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl_test.cc +++ b/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_impl_test.cc
@@ -8,14 +8,17 @@ #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/css/css_property_value_set.h" #include "third_party/blink/renderer/core/dom/dom_token_list.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/events/keyboard_event.h" #include "third_party/blink/renderer/core/frame/settings.h" +#include "third_party/blink/renderer/core/geometry/dom_rect.h" #include "third_party/blink/renderer/core/html/media/html_media_element.h" #include "third_party/blink/renderer/core/html/media/html_media_test_helper.h" #include "third_party/blink/renderer/core/html/media/html_video_element.h" +#include "third_party/blink/renderer/core/html/time_ranges.h" #include "third_party/blink/renderer/core/loader/empty_clients.h" #include "third_party/blink/renderer/core/testing/page_test_base.h" #include "third_party/blink/renderer/platform/keyboard_codes.h" @@ -30,7 +33,9 @@ public: WebTimeRanges Seekable() const override { return seekable_; } bool HasVideo() const override { return true; } + WebTimeRanges Buffered() const override { return buffered_; } + WebTimeRanges buffered_; WebTimeRanges seekable_; }; @@ -66,11 +71,11 @@ &clients, MakeGarbageCollected<test::MediaStubLocalFrameClient>( std::make_unique<MockWebMediaPlayerForTouchlessImpl>())); - GetDocument().write("<video>"); + GetDocument().write("<video controls>"); HTMLMediaElement& video = ToHTMLVideoElement(*GetDocument().QuerySelector("video")); - media_controls_ = MediaControlsTouchlessImpl::Create( - video, video.EnsureUserAgentShadowRoot()); + media_controls_ = + static_cast<MediaControlsTouchlessImpl*>(video.GetMediaControls()); } MediaControlsTouchlessImpl& MediaControls() { return *media_controls_; } @@ -98,6 +103,11 @@ MediaElement().DurationChanged(duration, false /* requestSeek */); } + void SetBufferedRange(double end) { + WebTimeRange time_range(0.0, end); + WebMediaPlayer()->buffered_.Assign(&time_range, 1); + } + bool IsControlsVisible() { return !MediaControls().classList().contains("transparent"); } @@ -232,6 +242,39 @@ ASSERT_FALSE(play_button->classList().contains("playing")); } +TEST_F(MediaControlsTouchlessImplTest, ProgressBar) { + const double duration = 100.0; + const double buffered = 60.0; + const double current_time = 15.0; + + LoadMediaWithDuration(duration); + SetBufferedRange(buffered); + MediaElement().setCurrentTime(current_time); + test::RunPendingTasks(); + + MediaElement().DispatchEvent(*Event::Create(event_type_names::kTimeupdate)); + + Element* timeline = + GetControlByShadowPseudoId("-internal-media-controls-touchless-timeline"); + Element* progress_bar = GetControlByShadowPseudoId( + "-internal-media-controls-touchless-timeline-progress"); + Element* loaded_bar = GetControlByShadowPseudoId( + "-internal-media-controls-touchless-timeline-loaded"); + + ASSERT_NE(nullptr, timeline); + ASSERT_NE(nullptr, progress_bar); + ASSERT_NE(nullptr, loaded_bar); + + double timeline_width = timeline->getBoundingClientRect()->width(); + double progress_bar_width = progress_bar->getBoundingClientRect()->width(); + double loaded_bar_width = loaded_bar->getBoundingClientRect()->width(); + ASSERT_GT(timeline_width, 0); + + EXPECT_DOUBLE_EQ(buffered / duration, loaded_bar_width / timeline_width); + EXPECT_DOUBLE_EQ(current_time / buffered, + progress_bar_width / loaded_bar_width); +} + TEST_F(MediaControlsTouchlessImplTestWithMockScheduler, ControlsShowAndHide) { // Controls should starts hidden. ASSERT_FALSE(IsControlsVisible());
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.cc b/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.cc index d29a590..7c3d8c3 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.cc +++ b/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener.cc
@@ -35,6 +35,7 @@ media_element_->addEventListener(event_type_names::kTimeupdate, this, false); media_element_->addEventListener(event_type_names::kDurationchange, this, false); + media_element_->addEventListener(event_type_names::kProgress, this, false); media_element_->addEventListener(event_type_names::kPlay, this, false); media_element_->addEventListener(event_type_names::kPause, this, false); @@ -70,6 +71,11 @@ observer->OnDurationChange(); return; } + if (event->type() == event_type_names::kProgress) { + for (auto& observer : observers_) + observer->OnLoadingProgress(); + return; + } if (event->type() == event_type_names::kPlay) { for (auto& observer : observers_) observer->OnPlay();
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener_observer.h b/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener_observer.h index bb3cf4b..947702d 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener_observer.h +++ b/third_party/blink/renderer/modules/media_controls/touchless/media_controls_touchless_media_event_listener_observer.h
@@ -17,6 +17,7 @@ virtual void OnFocusIn() = 0; virtual void OnTimeUpdate() = 0; virtual void OnDurationChange() = 0; + virtual void OnLoadingProgress() = 0; virtual void OnPlay() = 0; virtual void OnPause() = 0; virtual void OnError() = 0;
diff --git a/third_party/blink/renderer/modules/media_controls/touchless/resources/mediaControlsTouchless.css b/third_party/blink/renderer/modules/media_controls/touchless/resources/mediaControlsTouchless.css index 73488b4..a2e86f64 100644 --- a/third_party/blink/renderer/modules/media_controls/touchless/resources/mediaControlsTouchless.css +++ b/third_party/blink/renderer/modules/media_controls/touchless/resources/mediaControlsTouchless.css
@@ -97,3 +97,23 @@ background-position: center; background-repeat: no-repeat; } + +video::-internal-media-controls-touchless-timeline { + position: absolute; + bottom: 0; + width: 100%; + height: 4px; + background-color: rgba(0, 0, 0, 0.2); +} + +video::-internal-media-controls-touchless-timeline-loaded { + height: 100%; + border-radius: 0 2px 2px 0; + background-color: rgba(255, 255, 255, 0.54); +} + +video::-internal-media-controls-touchless-timeline-progress { + height: 100%; + border-radius: 0 2px 2px 0; + background-color: rgba(255, 255, 255, 1.0); +}
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc index f1ad9c9..bac7a0bf 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_video_device.cc
@@ -555,32 +555,6 @@ } } -WebMediaStreamTrack::DisplayCaptureSurfaceType ToWebDisplaySurface( - media::mojom::DisplayCaptureSurfaceType display_surface) { - switch (display_surface) { - case media::mojom::DisplayCaptureSurfaceType::MONITOR: - return WebMediaStreamTrack::DisplayCaptureSurfaceType::kMonitor; - case media::mojom::DisplayCaptureSurfaceType::WINDOW: - return WebMediaStreamTrack::DisplayCaptureSurfaceType::kWindow; - case media::mojom::DisplayCaptureSurfaceType::APPLICATION: - return WebMediaStreamTrack::DisplayCaptureSurfaceType::kApplication; - case media::mojom::DisplayCaptureSurfaceType::BROWSER: - return WebMediaStreamTrack::DisplayCaptureSurfaceType::kBrowser; - } -} - -WebMediaStreamTrack::CursorCaptureType ToWebCursorCaptureType( - media::mojom::CursorCaptureType cursor) { - switch (cursor) { - case media::mojom::CursorCaptureType::NEVER: - return WebMediaStreamTrack::CursorCaptureType::kNever; - case media::mojom::CursorCaptureType::ALWAYS: - return WebMediaStreamTrack::CursorCaptureType::kAlways; - case media::mojom::CursorCaptureType::MOTION: - return WebMediaStreamTrack::CursorCaptureType::kMotion; - } -} - VideoDeviceCaptureCapabilities::VideoDeviceCaptureCapabilities() = default; VideoDeviceCaptureCapabilities::VideoDeviceCaptureCapabilities( VideoDeviceCaptureCapabilities&& other) = default;
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc index 313e3eb..6a2ba35 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
@@ -532,16 +532,16 @@ if (platform_settings.display_surface) { WTF::String value; switch (platform_settings.display_surface.value()) { - case WebMediaStreamTrack::DisplayCaptureSurfaceType::kMonitor: + case media::mojom::DisplayCaptureSurfaceType::MONITOR: value = "monitor"; break; - case WebMediaStreamTrack::DisplayCaptureSurfaceType::kWindow: + case media::mojom::DisplayCaptureSurfaceType::WINDOW: value = "window"; break; - case WebMediaStreamTrack::DisplayCaptureSurfaceType::kApplication: + case media::mojom::DisplayCaptureSurfaceType::APPLICATION: value = "application"; break; - case WebMediaStreamTrack::DisplayCaptureSurfaceType::kBrowser: + case media::mojom::DisplayCaptureSurfaceType::BROWSER: value = "browser"; break; } @@ -552,13 +552,13 @@ if (platform_settings.cursor) { WTF::String value; switch (platform_settings.cursor.value()) { - case WebMediaStreamTrack::CursorCaptureType::kNever: + case media::mojom::CursorCaptureType::NEVER: value = "never"; break; - case WebMediaStreamTrack::CursorCaptureType::kAlways: + case media::mojom::CursorCaptureType::ALWAYS: value = "always"; break; - case WebMediaStreamTrack::CursorCaptureType::kMotion: + case media::mojom::CursorCaptureType::MOTION: value = "motion"; break; }
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc index a5860f8..b6b0f29 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
@@ -450,9 +450,9 @@ : WebMediaStreamTrack::kResizeModeNone)); if (source_->device().display_media_info.has_value()) { const auto& info = source_->device().display_media_info.value(); - settings.display_surface = ToWebDisplaySurface(info->display_surface); + settings.display_surface = info->display_surface; settings.logical_surface = info->logical_surface; - settings.cursor = ToWebCursorCaptureType(info->cursor); + settings.cursor = info->cursor; } }
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc index 093d1b3..cf44193 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -4529,9 +4529,9 @@ return; shader->SetSource(string); WTF::StringUTF8Adaptor adaptor(string_without_comments); - const GLchar* shader_data = adaptor.Data(); + const GLchar* shader_data = adaptor.data(); // TODO(danakj): Use base::saturated_cast<GLint>. - const GLint shader_length = adaptor.length(); + const GLint shader_length = adaptor.size(); ContextGL()->ShaderSource(ObjectOrZero(shader), 1, &shader_data, &shader_length); }
diff --git a/third_party/blink/renderer/platform/exported/web_string.cc b/third_party/blink/renderer/platform/exported/web_string.cc index 52b5189..c8406475 100644 --- a/third_party/blink/renderer/platform/exported/web_string.cc +++ b/third_party/blink/renderer/platform/exported/web_string.cc
@@ -82,7 +82,7 @@ std::string WebString::Utf8(UTF8ConversionMode mode) const { StringUTF8Adaptor utf8(impl_.get(), static_cast<WTF::UTF8ConversionMode>(mode)); - return std::string(utf8.Data(), utf8.length()); + return utf8.AsStdString(); } WebString WebString::FromUTF8(const char* data, size_t length) {
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc index 5de70cc..7872f3b 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
@@ -1197,7 +1197,7 @@ auto scroll = CreateScroll(ScrollPaintPropertyNode::Root(), ScrollState1(), kNotScrollingOnMain, scroll_element_id); auto scroll_translation = CreateScrollTranslation( - t0(), 7, 9, *scroll, CompositingReason::kWillChangeCompositingHint); + t0(), 7, 9, *scroll, CompositingReason::kWillChangeTransform); auto transform = CreateTransform( *scroll_translation, TransformationMatrix().Translate(5, 5), @@ -1236,7 +1236,7 @@ auto scroll_1 = CreateScroll(ScrollPaintPropertyNode::Root(), ScrollState1(), kNotScrollingOnMain, scroll_1_element_id); auto scroll_translation_1 = CreateScrollTranslation( - t0(), 7, 9, *scroll_1, CompositingReason::kWillChangeCompositingHint); + t0(), 7, 9, *scroll_1, CompositingReason::kWillChangeTransform); auto clip_2 = CreateClip(*clip_1, *scroll_translation_1, FloatRoundedRect(0, 0, 50, 50)); @@ -1244,7 +1244,7 @@ auto scroll_2 = CreateScroll(ScrollPaintPropertyNode::Root(), ScrollState2(), kNotScrollingOnMain, scroll_2_element_id); auto scroll_translation_2 = CreateScrollTranslation( - t0(), 0, 0, *scroll_2, CompositingReason::kWillChangeCompositingHint); + t0(), 0, 0, *scroll_2, CompositingReason::kWillChangeTransform); TestPaintArtifact artifact; CreateScrollableChunk(artifact, *scroll_translation_1, *clip_1->Parent(), @@ -2577,8 +2577,7 @@ FloatSize corner(5, 5); FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner, corner); - auto c1 = CreateClip(c0(), t0(), rrect, - CompositingReason::kWillChangeCompositingHint); + auto c1 = CreateClip(c0(), t0(), rrect); TestPaintArtifact artifact; artifact.Chunk(t0(), *c1, e0()) @@ -2628,7 +2627,7 @@ // applying clip path to a composited effect. auto c1 = CreateClipPathClip(c0(), t0(), FloatRoundedRect(50, 50, 300, 200)); auto e1 = CreateOpacityEffect(e0(), t0(), c1.get(), 1, - CompositingReason::kWillChangeCompositingHint); + CompositingReason::kWillChangeOpacity); TestPaintArtifact artifact; artifact.Chunk(t0(), *c1, *e1) @@ -2681,13 +2680,12 @@ // This tests the case that a two back-to-back composited layers having // the same composited rounded clip can share the synthesized mask. auto t1 = CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(), - CompositingReason::kWillChangeCompositingHint); + CompositingReason::kWillChangeTransform); FloatSize corner(5, 5); FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner, corner); - auto c1 = CreateClip(c0(), t0(), rrect, - CompositingReason::kWillChangeCompositingHint); + auto c1 = CreateClip(c0(), t0(), rrect); TestPaintArtifact artifact; artifact.Chunk(t0(), *c1, e0()) @@ -2750,13 +2748,12 @@ // composited rounded clip cannot share the synthesized mask if there is // another layer in the middle. auto t1 = CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(), - CompositingReason::kWillChangeCompositingHint); + CompositingReason::kWillChangeTransform); FloatSize corner(5, 5); FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner, corner); - auto c1 = CreateClip(c0(), t0(), rrect, - CompositingReason::kWillChangeCompositingHint); + auto c1 = CreateClip(c0(), t0(), rrect); TestPaintArtifact artifact; artifact.Chunk(t0(), *c1, e0()) @@ -2844,10 +2841,9 @@ FloatSize corner(5, 5); FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner, corner); - auto c1 = CreateClip(c0(), t0(), rrect, - CompositingReason::kWillChangeCompositingHint); + auto c1 = CreateClip(c0(), t0(), rrect); auto e1 = CreateOpacityEffect(e0(), t0(), c1.get(), 1, - CompositingReason::kWillChangeCompositingHint); + CompositingReason::kWillChangeOpacity); TestPaintArtifact artifact; artifact.Chunk(t0(), *c1, e0()) @@ -2914,13 +2910,12 @@ FloatSize corner(5, 5); FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner, corner); - auto c1 = CreateClip(c0(), t0(), rrect, - CompositingReason::kWillChangeCompositingHint); + auto c1 = CreateClip(c0(), t0(), rrect); CompositorFilterOperations non_trivial_filter; non_trivial_filter.AppendBlurFilter(5); auto e1 = CreateFilterEffect(e0(), non_trivial_filter, FloatPoint(), - CompositingReason::kWillChangeCompositingHint); + CompositingReason::kActiveFilterAnimation); TestPaintArtifact artifact; artifact.Chunk(t0(), *c1, e0()) @@ -3019,15 +3014,13 @@ FloatSize corner(5, 5); FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner, corner); - auto c1 = CreateClip(c0(), t0(), rrect, - CompositingReason::kWillChangeCompositingHint); + auto c1 = CreateClip(c0(), t0(), rrect); EffectPaintPropertyNode::State e1_state; e1_state.local_transform_space = &t0(); e1_state.output_clip = c1.get(); e1_state.blend_mode = SkBlendMode::kMultiply; - e1_state.direct_compositing_reasons = - CompositingReason::kWillChangeCompositingHint; + e1_state.direct_compositing_reasons = CompositingReason::kWillChangeOpacity; auto e1 = EffectPaintPropertyNode::Create(e0(), std::move(e1_state)); TestPaintArtifact artifact; @@ -3370,16 +3363,14 @@ // L0 L1 L5 auto e = CreateOpacityEffect(e0(), 0.1f); auto a = CreateOpacityEffect(*e, 0.2f); - auto b = CreateOpacityEffect(*e, 0.3f, - CompositingReason::kWillChangeCompositingHint); - auto c = CreateOpacityEffect(*e, 0.4f, - CompositingReason::kWillChangeCompositingHint); - auto aa = CreateOpacityEffect(*a, 0.5f, - CompositingReason::kWillChangeCompositingHint); - auto ab = CreateOpacityEffect(*a, 0.6f, - CompositingReason::kWillChangeCompositingHint); - auto ca = CreateOpacityEffect(*c, 0.7f, - CompositingReason::kWillChangeCompositingHint); + auto b = CreateOpacityEffect(*e, 0.3f, CompositingReason::kWillChangeOpacity); + auto c = CreateOpacityEffect(*e, 0.4f, CompositingReason::kWillChangeOpacity); + auto aa = + CreateOpacityEffect(*a, 0.5f, CompositingReason::kWillChangeOpacity); + auto ab = + CreateOpacityEffect(*a, 0.6f, CompositingReason::kWillChangeOpacity); + auto ca = + CreateOpacityEffect(*c, 0.7f, CompositingReason::kWillChangeOpacity); auto t = CreateTransform(t0(), TransformationMatrix().Rotate(90), FloatPoint3D(), CompositingReason::k3DTransform); @@ -3537,11 +3528,10 @@ TEST_P(PaintArtifactCompositorTest, OpacityIndirectlyAffectingTwoLayers) { auto opacity = CreateOpacityEffect(e0(), 0.5f); - auto child_composited_effect = CreateOpacityEffect( - *opacity, 1.f, CompositingReason::kWillChangeCompositingHint); - auto grandchild_composited_effect = - CreateOpacityEffect(*child_composited_effect, 1.f, - CompositingReason::kWillChangeCompositingHint); + auto child_composited_effect = + CreateOpacityEffect(*opacity, 1.f, CompositingReason::kWillChangeOpacity); + auto grandchild_composited_effect = CreateOpacityEffect( + *child_composited_effect, 1.f, CompositingReason::kWillChangeOpacity); TestPaintArtifact artifact; artifact.Chunk(t0(), c0(), *child_composited_effect) @@ -3616,7 +3606,7 @@ CompositorFilterOperations filter; filter.AppendBlurFilter(5); auto e1 = CreateFilterEffect(e0(), filter, FloatPoint(), - CompositingReason::kWillChangeCompositingHint); + CompositingReason::kActiveFilterAnimation); Update(TestPaintArtifact() .Chunk(t0(), c0(), *e1) .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite) @@ -3640,9 +3630,8 @@ TEST_P(PaintArtifactCompositorTest, BackdropFilterCreatesRenderSurface) { CompositorFilterOperations filter; filter.AppendBlurFilter(5); - auto e1 = - CreateBackdropFilterEffect(e0(), filter, FloatPoint(), - CompositingReason::kWillChangeCompositingHint); + auto e1 = CreateBackdropFilterEffect(e0(), filter, FloatPoint(), + CompositingReason::kBackdropFilter); Update(TestPaintArtifact() .Chunk(t0(), c0(), *e1) .RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite)
diff --git a/third_party/blink/renderer/platform/graphics/compositing_reasons.cc b/third_party/blink/renderer/platform/graphics/compositing_reasons.cc index b5824d8..ee60a09 100644 --- a/third_party/blink/renderer/platform/graphics/compositing_reasons.cc +++ b/third_party/blink/renderer/platform/graphics/compositing_reasons.cc
@@ -36,8 +36,6 @@ {CompositingReason::kActiveBackdropFilterAnimation, "activeBackdropFilterAnimation", "Has an active accelerated backdrop filter animation or transition"}, - {CompositingReason::kTransitionProperty, "transitionProperty", - "Has an acceleratable transition property (active or inactive)"}, {CompositingReason::kScrollDependentPosition, "scrollDependentPosition", "Is fixed or sticky position"}, {CompositingReason::kOverflowScrollingTouch, "overflowScrollingTouch", @@ -48,8 +46,12 @@ "Has clipping ancestor"}, {CompositingReason::kVideoOverlay, "videoOverlay", "Is overlay controls for video"}, - {CompositingReason::kWillChangeCompositingHint, "willChange", - "Has a will-change compositing hint"}, + {CompositingReason::kWillChangeTransform, "willChangeTransform", + "Has a will-change: transform compositing hint"}, + {CompositingReason::kWillChangeOpacity, "willChangeOpacity", + "Has a will-change: opacity compositing hint"}, + {CompositingReason::kWillChangeOther, "willChangeOther", + "Has a will-change compositing hint other than transform and opacity"}, {CompositingReason::kBackdropFilter, "backdropFilter", "Has a backdrop filter"}, {CompositingReason::kRootScroller, "rootScroller",
diff --git a/third_party/blink/renderer/platform/graphics/compositing_reasons.h b/third_party/blink/renderer/platform/graphics/compositing_reasons.h index cda21292..d6d89e28 100644 --- a/third_party/blink/renderer/platform/graphics/compositing_reasons.h +++ b/third_party/blink/renderer/platform/graphics/compositing_reasons.h
@@ -27,13 +27,16 @@ V(ActiveOpacityAnimation) \ V(ActiveFilterAnimation) \ V(ActiveBackdropFilterAnimation) \ - V(TransitionProperty) \ V(ScrollDependentPosition) \ V(OverflowScrollingTouch) \ V(OverflowScrollingParent) \ V(OutOfFlowClipping) \ V(VideoOverlay) \ - V(WillChangeCompositingHint) \ + V(WillChangeTransform) \ + V(WillChangeOpacity) \ + /* This flag is needed only when neither kWillChangeTransform nor \ + kWillChangeOpacity is set */ \ + V(WillChangeOther) \ V(BackdropFilter) \ V(RootScroller) \ V(ScrollTimelineTarget) \ @@ -121,7 +124,8 @@ kComboAllDirectStyleDeterminedReasons = k3DTransform | kBackfaceVisibilityHidden | kComboActiveAnimation | - kTransitionProperty | kWillChangeCompositingHint | kBackdropFilter, + kWillChangeTransform | kWillChangeOpacity | kWillChangeOther | + kBackdropFilter, kComboAllDirectNonStyleDeterminedReasons = kVideo | kCanvas | kPlugin | kIFrame | kOverflowScrollingParent | @@ -151,17 +155,13 @@ kOverlap | kAssumedOverlap | kOverflowScrollingParent, kDirectReasonsForTransformProperty = - k3DTransform | kWillChangeCompositingHint | + k3DTransform | kWillChangeTransform | kWillChangeOther | kPerspectiveWith3DDescendants | kPreserve3DWith3DDescendants | - // Currently, we create transform/effect/filter nodes for an element - // whenever any property is being animated so that the existence of the - // effect node implies the existence of all nodes. - // TODO(flackr): Check for nodes for each KeyframeModel target property - // instead of creating all nodes and only create a transform/effect/ - // filter node if needed, https://crbug.com/900241 - kComboActiveAnimation, - kDirectReasonsForEffectProperty = kComboActiveAnimation, - kDirectReasonsForFilterProperty = kComboActiveAnimation, + kActiveTransformAnimation, + kDirectReasonsForEffectProperty = kActiveOpacityAnimation | + kWillChangeOpacity | + kActiveBackdropFilterAnimation, + kDirectReasonsForFilterProperty = kActiveFilterAnimation, }; };
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_blend.cc b/third_party/blink/renderer/platform/graphics/filters/fe_blend.cc index 80f3535..062977d 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_blend.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_blend.cc
@@ -34,10 +34,6 @@ FEBlend::FEBlend(Filter* filter, BlendMode mode) : FilterEffect(filter), mode_(mode) {} -FEBlend* FEBlend::Create(Filter* filter, BlendMode mode) { - return MakeGarbageCollected<FEBlend>(filter, mode); -} - bool FEBlend::SetBlendMode(BlendMode mode) { if (mode_ == mode) return false;
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_blend.h b/third_party/blink/renderer/platform/graphics/filters/fe_blend.h index 0b23ad9..dfb3937 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_blend.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_blend.h
@@ -30,8 +30,6 @@ class PLATFORM_EXPORT FEBlend final : public FilterEffect { public: - static FEBlend* Create(Filter*, BlendMode); - FEBlend(Filter*, BlendMode); BlendMode GetBlendMode() const { return mode_; }
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_box_reflect.h b/third_party/blink/renderer/platform/graphics/filters/fe_box_reflect.h index a28d295..3c137e1 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_box_reflect.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_box_reflect.h
@@ -14,10 +14,6 @@ // Used to implement the -webkit-box-reflect property as a filter. class PLATFORM_EXPORT FEBoxReflect final : public FilterEffect { public: - static FEBoxReflect* Create(Filter* filter, const BoxReflection& reflection) { - return MakeGarbageCollected<FEBoxReflect>(filter, reflection); - } - FEBoxReflect(Filter*, const BoxReflection&); // FilterEffect implementation
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc b/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc index 616cb43..0558c30 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc
@@ -37,12 +37,6 @@ const Vector<float>& values) : FilterEffect(filter), type_(type), values_(values) {} -FEColorMatrix* FEColorMatrix::Create(Filter* filter, - ColorMatrixType type, - const Vector<float>& values) { - return MakeGarbageCollected<FEColorMatrix>(filter, type, values); -} - ColorMatrixType FEColorMatrix::GetType() const { return type_; }
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.h b/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.h index 212eb96..1621b60e 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.h
@@ -38,8 +38,6 @@ class PLATFORM_EXPORT FEColorMatrix final : public FilterEffect { public: - static FEColorMatrix* Create(Filter*, ColorMatrixType, const Vector<float>&); - FEColorMatrix(Filter*, ColorMatrixType, const Vector<float>&); ColorMatrixType GetType() const;
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.cc b/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.cc index 6a33e1f..431d16d 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.cc
@@ -49,16 +49,6 @@ blue_func_(blue_func), alpha_func_(alpha_func) {} -FEComponentTransfer* FEComponentTransfer::Create( - Filter* filter, - const ComponentTransferFunction& red_func, - const ComponentTransferFunction& green_func, - const ComponentTransferFunction& blue_func, - const ComponentTransferFunction& alpha_func) { - return MakeGarbageCollected<FEComponentTransfer>(filter, red_func, green_func, - blue_func, alpha_func); -} - static void Identity(unsigned char*, const ComponentTransferFunction&) {} static void Table(unsigned char* values,
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.h b/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.h index 1509883..d1d8e477 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_component_transfer.h
@@ -60,13 +60,6 @@ class PLATFORM_EXPORT FEComponentTransfer final : public FilterEffect { public: - static FEComponentTransfer* Create( - Filter*, - const ComponentTransferFunction& red_func, - const ComponentTransferFunction& green_func, - const ComponentTransferFunction& blue_func, - const ComponentTransferFunction& alpha_func); - FEComponentTransfer(Filter*, const ComponentTransferFunction& red_func, const ComponentTransferFunction& green_func,
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_composite.cc b/third_party/blink/renderer/platform/graphics/filters/fe_composite.cc index 2b0834f..f77cba2 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_composite.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_composite.cc
@@ -41,15 +41,6 @@ float k4) : FilterEffect(filter), type_(type), k1_(k1), k2_(k2), k3_(k3), k4_(k4) {} -FEComposite* FEComposite::Create(Filter* filter, - const CompositeOperationType& type, - float k1, - float k2, - float k3, - float k4) { - return MakeGarbageCollected<FEComposite>(filter, type, k1, k2, k3, k4); -} - CompositeOperationType FEComposite::Operation() const { return type_; }
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_composite.h b/third_party/blink/renderer/platform/graphics/filters/fe_composite.h index d416525a..90b2320 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_composite.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_composite.h
@@ -41,13 +41,6 @@ class PLATFORM_EXPORT FEComposite final : public FilterEffect { public: - static FEComposite* Create(Filter*, - const CompositeOperationType&, - float, - float, - float, - float); - FEComposite(Filter*, const CompositeOperationType&, float,
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_composite_test.cc b/third_party/blink/renderer/platform/graphics/filters/fe_composite_test.cc index 74972a9..ac95f36e 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_composite_test.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_composite_test.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/platform/graphics/filters/fe_offset.h" #include "third_party/blink/renderer/platform/graphics/filters/filter.h" #include "third_party/blink/renderer/platform/graphics/filters/source_graphic.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { @@ -21,21 +22,22 @@ // Use big filter region to avoid it from affecting FEComposite's MapRect // results. FloatRect filter_region(-10000, -10000, 20000, 20000); - auto* filter = - Filter::Create(FloatRect(), filter_region, 1, Filter::kUserSpace); + auto* filter = MakeGarbageCollected<Filter>(FloatRect(), filter_region, 1, + Filter::kUserSpace); // Input 1 of composite has a fixed output rect. - auto* source_graphic1 = SourceGraphic::Create(filter); + auto* source_graphic1 = MakeGarbageCollected<SourceGraphic>(filter); source_graphic1->SetClipsToBounds(false); source_graphic1->SetSourceRect(kInput1Rect); // Input 2 of composite will pass composite->MapRect()'s parameter as its // output. - auto* source_graphic2 = SourceGraphic::Create(filter); + auto* source_graphic2 = MakeGarbageCollected<SourceGraphic>(filter); source_graphic2->SetClipsToBounds(false); // Composite input 1 and input 2. - auto* composite = FEComposite::Create(filter, type, k1, k2, k3, k4); + auto* composite = + MakeGarbageCollected<FEComposite>(filter, type, k1, k2, k3, k4); composite->SetClipsToBounds(false); composite->InputEffects().push_back(source_graphic1); composite->InputEffects().push_back(source_graphic2);
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc b/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc index 2598ea2..261dcf6 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc
@@ -49,19 +49,6 @@ preserve_alpha_(preserve_alpha), kernel_matrix_(kernel_matrix) {} -FEConvolveMatrix* FEConvolveMatrix::Create(Filter* filter, - const IntSize& kernel_size, - float divisor, - float bias, - const IntPoint& target_offset, - EdgeModeType edge_mode, - bool preserve_alpha, - const Vector<float>& kernel_matrix) { - return MakeGarbageCollected<FEConvolveMatrix>(filter, kernel_size, divisor, - bias, target_offset, edge_mode, - preserve_alpha, kernel_matrix); -} - FloatRect FEConvolveMatrix::MapEffect(const FloatRect& rect) const { if (!ParametersValid()) return rect;
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.h b/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.h index 9212f5a..2dd262b 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.h
@@ -41,15 +41,6 @@ class PLATFORM_EXPORT FEConvolveMatrix final : public FilterEffect { public: - static FEConvolveMatrix* Create(Filter*, - const IntSize&, - float, - float, - const IntPoint&, - EdgeModeType, - bool, - const Vector<float>&); - FEConvolveMatrix(Filter*, const IntSize&, float,
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_diffuse_lighting.cc b/third_party/blink/renderer/platform/graphics/filters/fe_diffuse_lighting.cc index 8d0c99d..a041530 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_diffuse_lighting.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_diffuse_lighting.cc
@@ -41,17 +41,6 @@ 0, std::move(light_source)) {} -FEDiffuseLighting* FEDiffuseLighting::Create( - Filter* filter, - const Color& lighting_color, - float surface_scale, - float diffuse_constant, - scoped_refptr<LightSource> light_source) { - return MakeGarbageCollected<FEDiffuseLighting>( - filter, lighting_color, surface_scale, diffuse_constant, - std::move(light_source)); -} - FEDiffuseLighting::~FEDiffuseLighting() = default; Color FEDiffuseLighting::LightingColor() const {
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_diffuse_lighting.h b/third_party/blink/renderer/platform/graphics/filters/fe_diffuse_lighting.h index 5db5f8af..1d5353de 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_diffuse_lighting.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_diffuse_lighting.h
@@ -31,12 +31,6 @@ class PLATFORM_EXPORT FEDiffuseLighting final : public FELighting { public: - static FEDiffuseLighting* Create(Filter*, - const Color&, - float, - float, - scoped_refptr<LightSource>); - FEDiffuseLighting(Filter*, const Color&, float,
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.cc b/third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.cc index 02ecb59e..a82b346 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.cc
@@ -40,15 +40,6 @@ y_channel_selector_(y_channel_selector), scale_(scale) {} -FEDisplacementMap* FEDisplacementMap::Create( - Filter* filter, - ChannelSelectorType x_channel_selector, - ChannelSelectorType y_channel_selector, - float scale) { - return MakeGarbageCollected<FEDisplacementMap>(filter, x_channel_selector, - y_channel_selector, scale); -} - FloatRect FEDisplacementMap::MapEffect(const FloatRect& rect) const { FloatRect result = rect; result.InflateX(GetFilter()->ApplyHorizontalScale(std::abs(scale_) / 2));
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.h b/third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.h index fac11a8..952732b 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_displacement_map.h
@@ -37,11 +37,6 @@ class PLATFORM_EXPORT FEDisplacementMap final : public FilterEffect { public: - static FEDisplacementMap* Create(Filter*, - ChannelSelectorType x_channel_selector, - ChannelSelectorType y_channel_selector, - float); - FEDisplacementMap(Filter*, ChannelSelectorType x_channel_selector, ChannelSelectorType y_channel_selector,
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.cc b/third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.cc index e9d121f6..1a5fb28e 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.cc
@@ -43,17 +43,6 @@ shadow_color_(shadow_color), shadow_opacity_(shadow_opacity) {} -FEDropShadow* FEDropShadow::Create(Filter* filter, - float std_x, - float std_y, - float dx, - float dy, - const Color& shadow_color, - float shadow_opacity) { - return MakeGarbageCollected<FEDropShadow>(filter, std_x, std_y, dx, dy, - shadow_color, shadow_opacity); -} - FloatRect FEDropShadow::MapEffect(const FloatSize& std_deviation, const FloatPoint& offset, const FloatRect& rect) {
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.h b/third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.h index e3fa045..16ef4d2 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_drop_shadow.h
@@ -28,9 +28,6 @@ class PLATFORM_EXPORT FEDropShadow final : public FilterEffect { public: - static FEDropShadow* - Create(Filter*, float, float, float, float, const Color&, float); - FEDropShadow(Filter*, float, float, float, float, const Color&, float); // Compute which destination area will be affected when applying a drop
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_flood.cc b/third_party/blink/renderer/platform/graphics/filters/fe_flood.cc index 08715d1..795630b 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_flood.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_flood.cc
@@ -36,12 +36,6 @@ FilterEffect::SetOperatingInterpolationSpace(kInterpolationSpaceSRGB); } -FEFlood* FEFlood::Create(Filter* filter, - const Color& flood_color, - float flood_opacity) { - return MakeGarbageCollected<FEFlood>(filter, flood_color, flood_opacity); -} - Color FEFlood::FloodColor() const { return flood_color_; }
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_flood.h b/third_party/blink/renderer/platform/graphics/filters/fe_flood.h index 43147f60..1803563 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_flood.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_flood.h
@@ -30,8 +30,6 @@ class PLATFORM_EXPORT FEFlood final : public FilterEffect { public: - static FEFlood* Create(Filter*, const Color&, float); - FEFlood(Filter*, const Color&, float); Color FloodColor() const;
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.cc b/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.cc index 7be8b94..373144a 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.cc
@@ -59,10 +59,6 @@ FEGaussianBlur::FEGaussianBlur(Filter* filter, float x, float y) : FilterEffect(filter), std_x_(x), std_y_(y) {} -FEGaussianBlur* FEGaussianBlur::Create(Filter* filter, float x, float y) { - return MakeGarbageCollected<FEGaussianBlur>(filter, x, y); -} - FloatRect FEGaussianBlur::MapEffect(const FloatSize& std_deviation, const FloatRect& rect) { IntSize kernel_size = CalculateKernelSize(std_deviation);
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.h b/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.h index ec92a6eb..7f97f40 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.h
@@ -29,8 +29,6 @@ class PLATFORM_EXPORT FEGaussianBlur final : public FilterEffect { public: - static FEGaussianBlur* Create(Filter*, float, float); - FEGaussianBlur(Filter*, float, float); // Compute which destination area will be affected when applying a gaussian
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_merge.cc b/third_party/blink/renderer/platform/graphics/filters/fe_merge.cc index f3c40fe..6a1291c 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_merge.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_merge.cc
@@ -31,10 +31,6 @@ FEMerge::FEMerge(Filter* filter) : FilterEffect(filter) {} -FEMerge* FEMerge::Create(Filter* filter) { - return MakeGarbageCollected<FEMerge>(filter); -} - sk_sp<PaintFilter> FEMerge::CreateImageFilter() { unsigned size = NumberOfEffectInputs();
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_merge.h b/third_party/blink/renderer/platform/graphics/filters/fe_merge.h index 02dab02a..2e23910f 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_merge.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_merge.h
@@ -29,8 +29,6 @@ class PLATFORM_EXPORT FEMerge final : public FilterEffect { public: - static FEMerge* Create(Filter*); - explicit FEMerge(Filter*); WTF::TextStream& ExternalRepresentation(WTF::TextStream&,
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_morphology.cc b/third_party/blink/renderer/platform/graphics/filters/fe_morphology.cc index d8ee86f..52ec2fe 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_morphology.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_morphology.cc
@@ -40,13 +40,6 @@ radius_x_(std::max(0.0f, radius_x)), radius_y_(std::max(0.0f, radius_y)) {} -FEMorphology* FEMorphology::Create(Filter* filter, - MorphologyOperatorType type, - float radius_x, - float radius_y) { - return MakeGarbageCollected<FEMorphology>(filter, type, radius_x, radius_y); -} - MorphologyOperatorType FEMorphology::MorphologyOperator() const { return type_; }
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_morphology.h b/third_party/blink/renderer/platform/graphics/filters/fe_morphology.h index baa3ca6f4..d3a846d6 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_morphology.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_morphology.h
@@ -35,11 +35,6 @@ class PLATFORM_EXPORT FEMorphology final : public FilterEffect { public: - static FEMorphology* Create(Filter*, - MorphologyOperatorType, - float radius_x, - float radius_y); - FEMorphology(Filter*, MorphologyOperatorType, float radius_x, float radius_y); MorphologyOperatorType MorphologyOperator() const;
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_offset.cc b/third_party/blink/renderer/platform/graphics/filters/fe_offset.cc index f5844d6..bbe9f3c 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_offset.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_offset.cc
@@ -34,10 +34,6 @@ FEOffset::FEOffset(Filter* filter, float dx, float dy) : FilterEffect(filter), dx_(dx), dy_(dy) {} -FEOffset* FEOffset::Create(Filter* filter, float dx, float dy) { - return MakeGarbageCollected<FEOffset>(filter, dx, dy); -} - float FEOffset::Dx() const { return dx_; }
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_offset.h b/third_party/blink/renderer/platform/graphics/filters/fe_offset.h index b7c1f1b..bf65e55 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_offset.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_offset.h
@@ -29,8 +29,6 @@ class PLATFORM_EXPORT FEOffset final : public FilterEffect { public: - static FEOffset* Create(Filter*, float dx, float dy); - FEOffset(Filter*, float dx, float dy); float Dx() const;
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_specular_lighting.cc b/third_party/blink/renderer/platform/graphics/filters/fe_specular_lighting.cc index d2679a7..5bf5281 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_specular_lighting.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_specular_lighting.cc
@@ -44,18 +44,6 @@ specular_exponent, std::move(light_source)) {} -FESpecularLighting* FESpecularLighting::Create( - Filter* filter, - const Color& lighting_color, - float surface_scale, - float specular_constant, - float specular_exponent, - scoped_refptr<LightSource> light_source) { - return MakeGarbageCollected<FESpecularLighting>( - filter, lighting_color, surface_scale, specular_constant, - specular_exponent, std::move(light_source)); -} - FESpecularLighting::~FESpecularLighting() = default; Color FESpecularLighting::LightingColor() const {
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_specular_lighting.h b/third_party/blink/renderer/platform/graphics/filters/fe_specular_lighting.h index e35c0e4..96c9c2ed 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_specular_lighting.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_specular_lighting.h
@@ -29,13 +29,6 @@ class PLATFORM_EXPORT FESpecularLighting final : public FELighting { public: - static FESpecularLighting* Create(Filter*, - const Color&, - float, - float, - float, - scoped_refptr<LightSource>); - FESpecularLighting(Filter*, const Color&, float,
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_tile.cc b/third_party/blink/renderer/platform/graphics/filters/fe_tile.cc index 70cb722..f29c9f4 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_tile.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_tile.cc
@@ -30,10 +30,6 @@ FETile::FETile(Filter* filter) : FilterEffect(filter) {} -FETile* FETile::Create(Filter* filter) { - return MakeGarbageCollected<FETile>(filter); -} - FloatRect FETile::MapInputs(const FloatRect& rect) const { return AbsoluteBounds(); }
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_tile.h b/third_party/blink/renderer/platform/graphics/filters/fe_tile.h index 1a7b7c5..b20b4bf 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_tile.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_tile.h
@@ -29,8 +29,6 @@ class PLATFORM_EXPORT FETile final : public FilterEffect { public: - static FETile* Create(Filter*); - FETile(Filter*); WTF::TextStream& ExternalRepresentation(WTF::TextStream&,
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc b/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc index 05e4acf..1186e8b 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc +++ b/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.cc
@@ -47,18 +47,6 @@ seed_(seed), stitch_tiles_(stitch_tiles) {} -FETurbulence* FETurbulence::Create(Filter* filter, - TurbulenceType type, - float base_frequency_x, - float base_frequency_y, - int num_octaves, - float seed, - bool stitch_tiles) { - return MakeGarbageCollected<FETurbulence>(filter, type, base_frequency_x, - base_frequency_y, num_octaves, seed, - stitch_tiles); -} - TurbulenceType FETurbulence::GetType() const { return type_; }
diff --git a/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.h b/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.h index 21ef942..3ab4828 100644 --- a/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.h +++ b/third_party/blink/renderer/platform/graphics/filters/fe_turbulence.h
@@ -37,9 +37,6 @@ class PLATFORM_EXPORT FETurbulence final : public FilterEffect { public: - static FETurbulence* - Create(Filter*, TurbulenceType, float, float, int, float, bool); - FETurbulence(Filter*, TurbulenceType, float, float, int, float, bool); TurbulenceType GetType() const;
diff --git a/third_party/blink/renderer/platform/graphics/filters/filter.cc b/third_party/blink/renderer/platform/graphics/filters/filter.cc index 57ab7b7..515d6d7 100644 --- a/third_party/blink/renderer/platform/graphics/filters/filter.cc +++ b/third_party/blink/renderer/platform/graphics/filters/filter.cc
@@ -32,9 +32,13 @@ #include "third_party/blink/renderer/platform/graphics/filters/filter_effect.h" #include "third_party/blink/renderer/platform/graphics/filters/source_graphic.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { +Filter::Filter(float scale) + : Filter(FloatRect(), FloatRect(), scale, kUserSpace) {} + Filter::Filter(const FloatRect& reference_box, const FloatRect& filter_region, float scale, @@ -43,20 +47,7 @@ filter_region_(filter_region), scale_(scale), unit_scaling_(unit_scaling), - source_graphic_(SourceGraphic::Create(this)) {} - -Filter* Filter::Create(const FloatRect& reference_box, - const FloatRect& filter_region, - float scale, - UnitScaling unit_scaling) { - return MakeGarbageCollected<Filter>(reference_box, filter_region, scale, - unit_scaling); -} - -Filter* Filter::Create(float scale) { - return MakeGarbageCollected<Filter>(FloatRect(), FloatRect(), scale, - kUserSpace); -} + source_graphic_(MakeGarbageCollected<SourceGraphic>(this)) {} void Filter::Trace(blink::Visitor* visitor) { visitor->Trace(source_graphic_);
diff --git a/third_party/blink/renderer/platform/graphics/filters/filter.h b/third_party/blink/renderer/platform/graphics/filters/filter.h index ecdfd6c2..d5073d5 100644 --- a/third_party/blink/renderer/platform/graphics/filters/filter.h +++ b/third_party/blink/renderer/platform/graphics/filters/filter.h
@@ -38,12 +38,7 @@ public: enum UnitScaling { kUserSpace, kBoundingBox }; - static Filter* Create(const FloatRect& reference_box, - const FloatRect& filter_region, - float scale, - UnitScaling); - static Filter* Create(float scale); - + Filter(float scale); Filter(const FloatRect& reference_box, const FloatRect& filter_region, float scale,
diff --git a/third_party/blink/renderer/platform/graphics/filters/image_filter_builder_test.cc b/third_party/blink/renderer/platform/graphics/filters/image_filter_builder_test.cc index ad4f8c7..0c0eb2d 100644 --- a/third_party/blink/renderer/platform/graphics/filters/image_filter_builder_test.cc +++ b/third_party/blink/renderer/platform/graphics/filters/image_filter_builder_test.cc
@@ -29,6 +29,7 @@ #include "third_party/blink/renderer/platform/graphics/filters/filter.h" #include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h" #include "third_party/blink/renderer/platform/graphics/filters/source_graphic.h" +#include "third_party/blink/renderer/platform/heap/heap.h" using testing::Test; @@ -38,21 +39,21 @@ protected: void InterpolationSpaceTest() { // Build filter tree - Filter* reference_filter = Filter::Create(1.0f); + auto* reference_filter = MakeGarbageCollected<Filter>(1.0f); // Add a dummy source graphic input FilterEffect* source_effect = reference_filter->GetSourceGraphic(); source_effect->SetOperatingInterpolationSpace(kInterpolationSpaceSRGB); // Add a blur effect (with input : source) - FilterEffect* blur_effect = - FEGaussianBlur::Create(reference_filter, 3.0f, 3.0f); + auto* blur_effect = + MakeGarbageCollected<FEGaussianBlur>(reference_filter, 3.0f, 3.0f); blur_effect->SetOperatingInterpolationSpace(kInterpolationSpaceLinear); blur_effect->InputEffects().push_back(source_effect); // Add a blend effect (with inputs : blur, source) - FilterEffect* blend_effect = - FEBlend::Create(reference_filter, BlendMode::kNormal); + auto* blend_effect = + MakeGarbageCollected<FEBlend>(reference_filter, BlendMode::kNormal); blend_effect->SetOperatingInterpolationSpace(kInterpolationSpaceSRGB); FilterEffectVector& blend_inputs = blend_effect->InputEffects(); blend_inputs.ReserveCapacity(2); @@ -60,7 +61,7 @@ blend_inputs.push_back(blur_effect); // Add a merge effect (with inputs : blur, blend) - FilterEffect* merge_effect = FEMerge::Create(reference_filter); + auto* merge_effect = MakeGarbageCollected<FEMerge>(reference_filter); merge_effect->SetOperatingInterpolationSpace(kInterpolationSpaceLinear); FilterEffectVector& merge_inputs = merge_effect->InputEffects(); merge_inputs.ReserveCapacity(2);
diff --git a/third_party/blink/renderer/platform/graphics/filters/paint_filter_effect.cc b/third_party/blink/renderer/platform/graphics/filters/paint_filter_effect.cc index b7172f9..042813a 100644 --- a/third_party/blink/renderer/platform/graphics/filters/paint_filter_effect.cc +++ b/third_party/blink/renderer/platform/graphics/filters/paint_filter_effect.cc
@@ -17,11 +17,6 @@ PaintFilterEffect::~PaintFilterEffect() = default; -PaintFilterEffect* PaintFilterEffect::Create(Filter* filter, - const PaintFlags& flags) { - return MakeGarbageCollected<PaintFilterEffect>(filter, flags); -} - sk_sp<PaintFilter> PaintFilterEffect::CreateImageFilter() { return sk_make_sp<PaintFlagsPaintFilter>(flags_); }
diff --git a/third_party/blink/renderer/platform/graphics/filters/paint_filter_effect.h b/third_party/blink/renderer/platform/graphics/filters/paint_filter_effect.h index 5150316..cd24b79 100644 --- a/third_party/blink/renderer/platform/graphics/filters/paint_filter_effect.h +++ b/third_party/blink/renderer/platform/graphics/filters/paint_filter_effect.h
@@ -12,8 +12,6 @@ class PLATFORM_EXPORT PaintFilterEffect : public FilterEffect { public: - static PaintFilterEffect* Create(Filter*, const PaintFlags&); - PaintFilterEffect(Filter*, const PaintFlags&); ~PaintFilterEffect() override;
diff --git a/third_party/blink/renderer/platform/graphics/filters/source_alpha.cc b/third_party/blink/renderer/platform/graphics/filters/source_alpha.cc index 4559afff..99f9f1ce 100644 --- a/third_party/blink/renderer/platform/graphics/filters/source_alpha.cc +++ b/third_party/blink/renderer/platform/graphics/filters/source_alpha.cc
@@ -29,10 +29,6 @@ namespace blink { -SourceAlpha* SourceAlpha::Create(FilterEffect* source_effect) { - return MakeGarbageCollected<SourceAlpha>(source_effect); -} - SourceAlpha::SourceAlpha(FilterEffect* source_effect) : FilterEffect(source_effect->GetFilter()) { SetOperatingInterpolationSpace(source_effect->OperatingInterpolationSpace());
diff --git a/third_party/blink/renderer/platform/graphics/filters/source_alpha.h b/third_party/blink/renderer/platform/graphics/filters/source_alpha.h index 4997830..9c6da57 100644 --- a/third_party/blink/renderer/platform/graphics/filters/source_alpha.h +++ b/third_party/blink/renderer/platform/graphics/filters/source_alpha.h
@@ -27,8 +27,6 @@ class PLATFORM_EXPORT SourceAlpha final : public FilterEffect { public: - static SourceAlpha* Create(FilterEffect*); - explicit SourceAlpha(FilterEffect*); WTF::TextStream& ExternalRepresentation(WTF::TextStream&,
diff --git a/third_party/blink/renderer/platform/graphics/filters/source_graphic.cc b/third_party/blink/renderer/platform/graphics/filters/source_graphic.cc index a4871a8..8e91d13 100644 --- a/third_party/blink/renderer/platform/graphics/filters/source_graphic.cc +++ b/third_party/blink/renderer/platform/graphics/filters/source_graphic.cc
@@ -31,10 +31,6 @@ SourceGraphic::~SourceGraphic() = default; -SourceGraphic* SourceGraphic::Create(Filter* filter) { - return MakeGarbageCollected<SourceGraphic>(filter); -} - FloatRect SourceGraphic::MapInputs(const FloatRect& rect) const { return !source_rect_.IsEmpty() ? FloatRect(source_rect_) : rect; }
diff --git a/third_party/blink/renderer/platform/graphics/filters/source_graphic.h b/third_party/blink/renderer/platform/graphics/filters/source_graphic.h index 76cc9af..335f44b 100644 --- a/third_party/blink/renderer/platform/graphics/filters/source_graphic.h +++ b/third_party/blink/renderer/platform/graphics/filters/source_graphic.h
@@ -29,8 +29,6 @@ class PLATFORM_EXPORT SourceGraphic final : public FilterEffect { public: - static SourceGraphic* Create(Filter*); - explicit SourceGraphic(Filter*); ~SourceGraphic() override;
diff --git a/third_party/blink/renderer/platform/graphics/logging_canvas.cc b/third_party/blink/renderer/platform/graphics/logging_canvas.cc index 74f9c32..a648a6a 100644 --- a/third_party/blink/renderer/platform/graphics/logging_canvas.cc +++ b/third_party/blink/renderer/platform/graphics/logging_canvas.cc
@@ -319,11 +319,7 @@ } std::unique_ptr<JSONObject> ObjectForSkShader(const SkShader& shader) { - auto shader_item = std::make_unique<JSONObject>(); - const SkMatrix local_matrix = shader.getLocalMatrix(); - if (!local_matrix.isIdentity()) - shader_item->SetArray("localMatrix", ArrayForSkMatrix(local_matrix)); - return shader_item; + return std::make_unique<JSONObject>(); } String StringForSkColor(const SkColor& color) {
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc b/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc index d3c4e58..8a41fa8 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc +++ b/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc
@@ -49,11 +49,9 @@ // If this DCHECKs are hit we are missing a call to update the properties. // See: ScopedPaintChunkProperties. DCHECK(!IsInInitialState()); + // At this point we should have all of the properties given to us. + DCHECK(current_properties_.IsInitialized()); #endif - // TODO(crbug.com/923729): This CHECK is a temporary to determine the cause of - // the referenced bug. At this point we should have all of the properties - // given to us. - CHECK(current_properties_.IsInitialized()); bool item_forces_new_chunk = item.IsForeignLayer() || item.IsScrollHitTest(); if (item_forces_new_chunk)
diff --git a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h index d407f039..5fa74731 100644 --- a/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h +++ b/third_party/blink/renderer/platform/graphics/paint/property_tree_state.h
@@ -21,11 +21,9 @@ const ClipPaintPropertyNode& clip, const EffectPaintPropertyNode& effect) : transform_(&transform), clip_(&clip), effect_(&effect) { - // TODO(crbug.com/923729): These CHECKs are temporary to determine the cause - // of the referenced bug. - CHECK(transform_); - CHECK(clip_); - CHECK(effect_); + DCHECK(transform_); + DCHECK(clip_); + DCHECK(effect_); } static const PropertyTreeState& Root(); @@ -49,9 +47,7 @@ } void SetTransform(const TransformPaintPropertyNode& node) { transform_ = &node; - // TODO(crbug.com/923729): This CHECK is temporary to determine the cause - // of the referenced bug. - CHECK(transform_); + DCHECK(transform_); } const ClipPaintPropertyNode& Clip() const { @@ -60,9 +56,7 @@ } void SetClip(const ClipPaintPropertyNode& node) { clip_ = &node; - // TODO(crbug.com/923729): This CHECK is temporary to determine the cause - // of the referenced bug. - CHECK(clip_); + DCHECK(clip_); } const EffectPaintPropertyNode& Effect() const { @@ -71,9 +65,7 @@ } void SetEffect(const EffectPaintPropertyNode& node) { effect_ = &node; - // TODO(crbug.com/923729): This CHECK is temporary to determine the cause - // of the referenced bug. - CHECK(effect_); + DCHECK(effect_); } void ClearChangedToRoot() const {
diff --git a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc index a39cd7e..7abd302 100644 --- a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc +++ b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
@@ -219,11 +219,6 @@ class Object : public GarbageCollected<Object> { public: - static Object* Create() { return MakeGarbageCollected<Object>(); } - static Object* Create(Object* next) { - return MakeGarbageCollected<Object>(next); - } - Object() : next_(nullptr) {} explicit Object(Object* next) : next_(next) {} @@ -255,7 +250,7 @@ } TEST(IncrementalMarkingTest, ManualWriteBarrierTriggersWhenMarkingIsOn) { - Object* object = Object::Create(); + auto* object = MakeGarbageCollected<Object>(); { ExpectWriteBarrierFires scope(ThreadState::Current(), {object}); EXPECT_FALSE(object->IsMarked()); @@ -265,7 +260,7 @@ } TEST(IncrementalMarkingTest, ManualWriteBarrierBailoutWhenMarkingIsOff) { - Object* object = Object::Create(); + auto* object = MakeGarbageCollected<Object>(); EXPECT_FALSE(object->IsMarked()); MarkingVisitor::WriteBarrier(object); EXPECT_FALSE(object->IsMarked()); @@ -276,8 +271,8 @@ // ============================================================================= TEST(IncrementalMarkingTest, MemberSetUnmarkedObject) { - Object* parent = Object::Create(); - Object* child = Object::Create(); + auto* parent = MakeGarbageCollected<Object>(); + auto* child = MakeGarbageCollected<Object>(); { ExpectWriteBarrierFires scope(ThreadState::Current(), {child}); EXPECT_FALSE(child->IsMarked()); @@ -287,8 +282,8 @@ } TEST(IncrementalMarkingTest, MemberSetMarkedObjectNoBarrier) { - Object* parent = Object::Create(); - Object* child = Object::Create(); + auto* parent = MakeGarbageCollected<Object>(); + auto* child = MakeGarbageCollected<Object>(); HeapObjectHeader::FromPayload(child)->Mark(); { ExpectNoWriteBarrierFires scope(ThreadState::Current(), {child}); @@ -297,12 +292,12 @@ } TEST(IncrementalMarkingTest, MemberInitializingStoreNoBarrier) { - Object* object1 = Object::Create(); + auto* object1 = MakeGarbageCollected<Object>(); HeapObjectHeader* object1_header = HeapObjectHeader::FromPayload(object1); { IncrementalMarkingScope scope(ThreadState::Current()); EXPECT_FALSE(object1_header->IsMarked()); - Object* object2 = Object::Create(object1); + auto* object2 = MakeGarbageCollected<Object>(object1); HeapObjectHeader* object2_header = HeapObjectHeader::FromPayload(object2); EXPECT_FALSE(object1_header->IsMarked()); EXPECT_FALSE(object2_header->IsMarked()); @@ -310,7 +305,7 @@ } TEST(IncrementalMarkingTest, MemberReferenceAssignMember) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); Member<Object> m1; Member<Object>& m2 = m1; Member<Object> m3(obj); @@ -345,7 +340,7 @@ } TEST(IncrementalMarkingTest, MemberHashTraitIsDeletedValueNoBarrier) { - Member<Object> m1(Object::Create()); + Member<Object> m1(MakeGarbageCollected<Object>()); { ExpectNoWriteBarrierFires scope(ThreadState::Current(), {}); EXPECT_FALSE(HashTraits<Member<Object>>::IsDeletedValue(m1)); @@ -382,8 +377,6 @@ USING_GARBAGE_COLLECTED_MIXIN(Child); public: - static Child* Create() { return MakeGarbageCollected<Child>(); } - Child() : ClassWithVirtual(), Mixin() {} ~Child() override {} @@ -395,10 +388,6 @@ class ParentWithMixinPointer : public GarbageCollected<ParentWithMixinPointer> { public: - static ParentWithMixinPointer* Create() { - return MakeGarbageCollected<ParentWithMixinPointer>(); - } - ParentWithMixinPointer() : mixin_(nullptr) {} void set_mixin(Mixin* mixin) { mixin_ = mixin; } @@ -412,8 +401,9 @@ } // namespace TEST(IncrementalMarkingTest, WriteBarrierOnUnmarkedMixinApplication) { - ParentWithMixinPointer* parent = ParentWithMixinPointer::Create(); - Child* child = Child::Create(); + ParentWithMixinPointer* parent = + MakeGarbageCollected<ParentWithMixinPointer>(); + auto* child = MakeGarbageCollected<Child>(); Mixin* mixin = static_cast<Mixin*>(child); EXPECT_NE(static_cast<void*>(child), static_cast<void*>(mixin)); { @@ -423,8 +413,9 @@ } TEST(IncrementalMarkingTest, NoWriteBarrierOnMarkedMixinApplication) { - ParentWithMixinPointer* parent = ParentWithMixinPointer::Create(); - Child* child = Child::Create(); + ParentWithMixinPointer* parent = + MakeGarbageCollected<ParentWithMixinPointer>(); + auto* child = MakeGarbageCollected<Child>(); HeapObjectHeader::FromPayload(child)->Mark(); Mixin* mixin = static_cast<Mixin*>(child); EXPECT_NE(static_cast<void*>(child), static_cast<void*>(mixin)); @@ -477,7 +468,7 @@ } // namespace TEST(IncrementalMarkingTest, HeapVectorPushBackMember) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); HeapVector<Member<Object>> vec; { ExpectWriteBarrierFires scope(ThreadState::Current(), {obj}); @@ -486,7 +477,7 @@ } TEST(IncrementalMarkingTest, HeapVectorPushBackNonGCedContainer) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); HeapVector<NonGarbageCollectedContainer> vec; { ExpectWriteBarrierFires scope(ThreadState::Current(), {obj}); @@ -495,8 +486,8 @@ } TEST(IncrementalMarkingTest, HeapVectorPushBackStdPair) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapVector<std::pair<Member<Object>, Member<Object>>> vec; { ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2}); @@ -505,7 +496,7 @@ } TEST(IncrementalMarkingTest, HeapVectorEmplaceBackMember) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); HeapVector<Member<Object>> vec; { ExpectWriteBarrierFires scope(ThreadState::Current(), {obj}); @@ -514,7 +505,7 @@ } TEST(IncrementalMarkingTest, HeapVectorEmplaceBackNonGCedContainer) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); HeapVector<NonGarbageCollectedContainer> vec; { ExpectWriteBarrierFires scope(ThreadState::Current(), {obj}); @@ -523,8 +514,8 @@ } TEST(IncrementalMarkingTest, HeapVectorEmplaceBackStdPair) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapVector<std::pair<Member<Object>, Member<Object>>> vec; { ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2}); @@ -533,7 +524,7 @@ } TEST(IncrementalMarkingTest, HeapVectorCopyMember) { - Object* object = Object::Create(); + auto* object = MakeGarbageCollected<Object>(); HeapVector<Member<Object>> vec1; vec1.push_back(object); { @@ -543,7 +534,7 @@ } TEST(IncrementalMarkingTest, HeapVectorCopyNonGCedContainer) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); HeapVector<NonGarbageCollectedContainer> vec1; vec1.emplace_back(obj, 1); { @@ -553,8 +544,8 @@ } TEST(IncrementalMarkingTest, HeapVectorCopyStdPair) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapVector<std::pair<Member<Object>, Member<Object>>> vec1; vec1.emplace_back(obj1, obj2); { @@ -564,7 +555,7 @@ } TEST(IncrementalMarkingTest, HeapVectorMoveMember) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); HeapVector<Member<Object>> vec1; vec1.push_back(obj); { @@ -574,7 +565,7 @@ } TEST(IncrementalMarkingTest, HeapVectorMoveNonGCedContainer) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); HeapVector<NonGarbageCollectedContainer> vec1; vec1.emplace_back(obj, 1); { @@ -584,8 +575,8 @@ } TEST(IncrementalMarkingTest, HeapVectorMoveStdPair) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapVector<std::pair<Member<Object>, Member<Object>>> vec1; vec1.emplace_back(obj1, obj2); { @@ -595,8 +586,8 @@ } TEST(IncrementalMarkingTest, HeapVectorSwapMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapVector<Member<Object>> vec1; vec1.push_back(obj1); HeapVector<Member<Object>> vec2; @@ -608,8 +599,8 @@ } TEST(IncrementalMarkingTest, HeapVectorSwapNonGCedContainer) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapVector<NonGarbageCollectedContainer> vec1; vec1.emplace_back(obj1, 1); HeapVector<NonGarbageCollectedContainer> vec2; @@ -621,8 +612,8 @@ } TEST(IncrementalMarkingTest, HeapVectorSwapStdPair) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapVector<std::pair<Member<Object>, Member<Object>>> vec1; vec1.emplace_back(obj1, nullptr); HeapVector<std::pair<Member<Object>, Member<Object>>> vec2; @@ -634,8 +625,8 @@ } TEST(IncrementalMarkingTest, HeapVectorSubscriptOperator) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapVector<Member<Object>> vec; vec.push_back(obj1); { @@ -649,9 +640,9 @@ } TEST(IncrementalMarkingTest, HeapVectorEagerTracingStopsAtMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); - Object* obj3 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); + auto* obj3 = MakeGarbageCollected<Object>(); obj1->set_next(obj3); HeapVector<NonGarbageCollectedContainerRoot> vec; { @@ -691,7 +682,7 @@ } // namespace TEST(IncrementalMarkingTest, HeapDoublyLinkedListPush) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); ObjectNode* obj_node = MakeGarbageCollected<ObjectNode>(obj); HeapDoublyLinkedList<ObjectNode> list; { @@ -703,7 +694,7 @@ } TEST(IncrementalMarkingTest, HeapDoublyLinkedListAppend) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); ObjectNode* obj_node = MakeGarbageCollected<ObjectNode>(obj); HeapDoublyLinkedList<ObjectNode> list; { @@ -719,7 +710,7 @@ // ============================================================================= TEST(IncrementalMarkingTest, HeapDequePushBackMember) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); HeapDeque<Member<Object>> deq; { ExpectWriteBarrierFires scope(ThreadState::Current(), {obj}); @@ -728,7 +719,7 @@ } TEST(IncrementalMarkingTest, HeapDequePushFrontMember) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); HeapDeque<Member<Object>> deq; { ExpectWriteBarrierFires scope(ThreadState::Current(), {obj}); @@ -737,7 +728,7 @@ } TEST(IncrementalMarkingTest, HeapDequeEmplaceBackMember) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); HeapDeque<Member<Object>> deq; { ExpectWriteBarrierFires scope(ThreadState::Current(), {obj}); @@ -746,7 +737,7 @@ } TEST(IncrementalMarkingTest, HeapDequeEmplaceFrontMember) { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); HeapDeque<Member<Object>> deq; { ExpectWriteBarrierFires scope(ThreadState::Current(), {obj}); @@ -755,7 +746,7 @@ } TEST(IncrementalMarkingTest, HeapDequeCopyMember) { - Object* object = Object::Create(); + auto* object = MakeGarbageCollected<Object>(); HeapDeque<Member<Object>> deq1; deq1.push_back(object); { @@ -765,7 +756,7 @@ } TEST(IncrementalMarkingTest, HeapDequeMoveMember) { - Object* object = Object::Create(); + auto* object = MakeGarbageCollected<Object>(); HeapDeque<Member<Object>> deq1; deq1.push_back(object); { @@ -775,8 +766,8 @@ } TEST(IncrementalMarkingTest, HeapDequeSwapMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapDeque<Member<Object>> deq1; deq1.push_back(obj1); HeapDeque<Member<Object>> deq2; @@ -795,7 +786,7 @@ template <typename Container> void Insert() { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); Container container; { ExpectWriteBarrierFires scope(ThreadState::Current(), {obj}); @@ -805,7 +796,7 @@ template <typename Container> void InsertNoBarrier() { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); Container container; { ExpectNoWriteBarrierFires scope(ThreadState::Current(), {obj}); @@ -815,7 +806,7 @@ template <typename Container> void Copy() { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); Container container1; container1.insert(obj); { @@ -828,7 +819,7 @@ template <typename Container> void CopyNoBarrier() { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); Container container1; container1.insert(obj); { @@ -841,7 +832,7 @@ template <typename Container> void Move() { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); Container container1; Container container2; container1.insert(obj); @@ -853,7 +844,7 @@ template <typename Container> void MoveNoBarrier() { - Object* obj = Object::Create(); + auto* obj = MakeGarbageCollected<Object>(); Container container1; container1.insert(obj); { @@ -864,8 +855,8 @@ template <typename Container> void Swap() { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); Container container1; container1.insert(obj1); Container container2; @@ -878,8 +869,8 @@ template <typename Container> void SwapNoBarrier() { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); Container container1; container1.insert(obj1); Container container2; @@ -1009,8 +1000,8 @@ namespace incremental_marking_test { TEST(IncrementalMarkingTest, HeapHashSetStrongWeakPair) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashSet<StrongWeakPair> set; { // Both, the weak and the strong field, are hit by the write barrier. @@ -1020,8 +1011,8 @@ } TEST(IncrementalMarkingTest, HeapLinkedHashSetStrongWeakPair) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapLinkedHashSet<StrongWeakPair> set; { // Both, the weak and the strong field, are hit by the write barrier. @@ -1073,8 +1064,8 @@ TEST(IncrementalMarkingTest, HeapHashCountedSetSwap) { // HeapHashCountedSet is not move constructible so we cannot use std::swap. { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashCountedSet<Member<Object>> container1; container1.insert(obj1); HeapHashCountedSet<Member<Object>> container2; @@ -1085,8 +1076,8 @@ } } { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashCountedSet<WeakMember<Object>> container1; container1.insert(obj1); HeapHashCountedSet<WeakMember<Object>> container2; @@ -1104,8 +1095,8 @@ // ============================================================================= TEST(IncrementalMarkingTest, HeapHashMapInsertMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, Member<Object>> map; { ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2}); @@ -1114,8 +1105,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapInsertWeakMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<WeakMember<Object>, WeakMember<Object>> map; { // Weak references are strongified for the current cycle. @@ -1125,8 +1116,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapInsertMemberWeakMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, WeakMember<Object>> map; { // Weak references are strongified for the current cycle. @@ -1136,8 +1127,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapInsertWeakMemberMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<WeakMember<Object>, Member<Object>> map; { // Weak references are strongified for the current cycle. @@ -1147,8 +1138,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapSetMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, Member<Object>> map; { ExpectWriteBarrierFires scope(ThreadState::Current(), {obj1, obj2}); @@ -1157,9 +1148,9 @@ } TEST(IncrementalMarkingTest, HeapHashMapSetMemberUpdateValue) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); - Object* obj3 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); + auto* obj3 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, Member<Object>> map; map.insert(obj1, obj2); { @@ -1173,9 +1164,9 @@ } TEST(IncrementalMarkingTest, HeapHashMapIteratorChangeKey) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); - Object* obj3 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); + auto* obj3 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, Member<Object>> map; map.insert(obj1, obj2); { @@ -1187,9 +1178,9 @@ } TEST(IncrementalMarkingTest, HeapHashMapIteratorChangeValue) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); - Object* obj3 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); + auto* obj3 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, Member<Object>> map; map.insert(obj1, obj2); { @@ -1201,8 +1192,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapCopyMemberMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, Member<Object>> map1; map1.insert(obj1, obj2); { @@ -1215,8 +1206,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapCopyWeakMemberWeakMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<WeakMember<Object>, WeakMember<Object>> map1; map1.insert(obj1, obj2); { @@ -1230,8 +1221,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapCopyMemberWeakMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, WeakMember<Object>> map1; map1.insert(obj1, obj2); { @@ -1245,8 +1236,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapCopyWeakMemberMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<WeakMember<Object>, Member<Object>> map1; map1.insert(obj1, obj2); { @@ -1260,8 +1251,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapMoveMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, Member<Object>> map1; map1.insert(obj1, obj2); { @@ -1271,8 +1262,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapMoveWeakMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<WeakMember<Object>, WeakMember<Object>> map1; map1.insert(obj1, obj2); { @@ -1283,8 +1274,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapMoveMemberWeakMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, WeakMember<Object>> map1; map1.insert(obj1, obj2); { @@ -1295,8 +1286,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapMoveWeakMemberMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<WeakMember<Object>, Member<Object>> map1; map1.insert(obj1, obj2); { @@ -1307,10 +1298,10 @@ } TEST(IncrementalMarkingTest, HeapHashMapSwapMemberMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); - Object* obj3 = Object::Create(); - Object* obj4 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); + auto* obj3 = MakeGarbageCollected<Object>(); + auto* obj4 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, Member<Object>> map1; map1.insert(obj1, obj2); HeapHashMap<Member<Object>, Member<Object>> map2; @@ -1323,10 +1314,10 @@ } TEST(IncrementalMarkingTest, HeapHashMapSwapWeakMemberWeakMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); - Object* obj3 = Object::Create(); - Object* obj4 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); + auto* obj3 = MakeGarbageCollected<Object>(); + auto* obj4 = MakeGarbageCollected<Object>(); HeapHashMap<WeakMember<Object>, WeakMember<Object>> map1; map1.insert(obj1, obj2); HeapHashMap<WeakMember<Object>, WeakMember<Object>> map2; @@ -1340,10 +1331,10 @@ } TEST(IncrementalMarkingTest, HeapHashMapSwapMemberWeakMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); - Object* obj3 = Object::Create(); - Object* obj4 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); + auto* obj3 = MakeGarbageCollected<Object>(); + auto* obj4 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, WeakMember<Object>> map1; map1.insert(obj1, obj2); HeapHashMap<Member<Object>, WeakMember<Object>> map2; @@ -1357,10 +1348,10 @@ } TEST(IncrementalMarkingTest, HeapHashMapSwapWeakMemberMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); - Object* obj3 = Object::Create(); - Object* obj4 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); + auto* obj3 = MakeGarbageCollected<Object>(); + auto* obj4 = MakeGarbageCollected<Object>(); HeapHashMap<WeakMember<Object>, Member<Object>> map1; map1.insert(obj1, obj2); HeapHashMap<WeakMember<Object>, Member<Object>> map2; @@ -1374,9 +1365,9 @@ } TEST(IncrementalMarkingTest, HeapHashMapInsertStrongWeakPairMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); - Object* obj3 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); + auto* obj3 = MakeGarbageCollected<Object>(); HeapHashMap<StrongWeakPair, Member<Object>> map; { // Tests that the write barrier also fires for entities such as @@ -1387,9 +1378,9 @@ } TEST(IncrementalMarkingTest, HeapHashMapInsertMemberStrongWeakPair) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); - Object* obj3 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); + auto* obj3 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, StrongWeakPair> map; { // Tests that the write barrier also fires for entities such as @@ -1400,8 +1391,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapCopyKeysToVectorMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, Member<Object>> map; map.insert(obj1, obj2); HeapVector<Member<Object>> vec; @@ -1414,8 +1405,8 @@ } TEST(IncrementalMarkingTest, HeapHashMapCopyValuesToVectorMember) { - Object* obj1 = Object::Create(); - Object* obj2 = Object::Create(); + auto* obj1 = MakeGarbageCollected<Object>(); + auto* obj2 = MakeGarbageCollected<Object>(); HeapHashMap<Member<Object>, Member<Object>> map; map.insert(obj1, obj2); HeapVector<Member<Object>> vec; @@ -1433,7 +1424,7 @@ TEST(IncrementalMarkingTest, DISABLED_WeakHashMapPromptlyFreeDisabled) { ThreadState* state = ThreadState::Current(); state->SetGCState(ThreadState::kIncrementalMarkingStepScheduled); - Persistent<Object> obj1 = Object::Create(); + Persistent<Object> obj1 = MakeGarbageCollected<Object>(); NormalPageArena* arena = static_cast<NormalPageArena*>( ThreadState::Current()->Heap().Arena(BlinkGC::kHashTableArenaIndex)); CHECK(arena); @@ -1606,7 +1597,7 @@ using WeakStore = HeapHashCountedSet<WeakMember<Object>>; Persistent<WeakStore> persistent(new WeakStore); - persistent->insert(Object::Create()); + persistent->insert(MakeGarbageCollected<Object>()); IncrementalMarkingTestDriver driver(ThreadState::Current()); driver.Start(); driver.FinishSteps(); @@ -1627,8 +1618,8 @@ // structure. The values for .second are chosen to be non-null as they // would otherwise count as empty and be skipped during iteration after the // first part died. - persistent->insert({Object::Create(), 1}); - persistent->insert({Object::Create(), 2}); + persistent->insert({MakeGarbageCollected<Object>(), 1}); + persistent->insert({MakeGarbageCollected<Object>(), 2}); IncrementalMarkingTestDriver driver(ThreadState::Current()); driver.Start(); // The backing is not treated as weak backing and thus eagerly processed, @@ -1662,11 +1653,11 @@ // would trigger the write barrier, mitigating the bug where a backing store // is promptly freed. for (size_t i = 0; i < 8; i++) { - persistent->insert({Object::Create(), i}); + persistent->insert({MakeGarbageCollected<Object>(), i}); } IncrementalMarkingTestDriver driver(ThreadState::Current()); driver.Start(); - persistent->insert({Object::Create(), 8}); + persistent->insert({MakeGarbageCollected<Object>(), 8}); // Is not allowed to free the backing store as the previous insert may have // registered a slot. persistent->clear(); @@ -1678,7 +1669,7 @@ using Store = HeapHashCountedSet<Member<Object>>; Persistent<Store> persistent(new Store()); - persistent->insert(Object::Create()); + persistent->insert(MakeGarbageCollected<Object>()); IncrementalMarkingTestDriver driver(ThreadState::Current()); HeapCompact::ScheduleCompactionGCForTesting(true); driver.Start(); @@ -1697,7 +1688,7 @@ IncrementalMarkingTestDriver driver(ThreadState::Current()); HeapCompact::ScheduleCompactionGCForTesting(true); - persistent->push_back(Object::Create()); + persistent->push_back(MakeGarbageCollected<Object>()); driver.Start(); driver.FinishGC(); @@ -1720,7 +1711,7 @@ HeapCompact::ScheduleCompactionGCForTesting(true); driver.Start(); driver.FinishSteps(); - persistent->insert(Object::Create()); + persistent->insert(MakeGarbageCollected<Object>()); driver.FinishGC(); // Weak callback should register the slot. @@ -1730,7 +1721,7 @@ TEST(IncrementalMarkingTest, ConservativeGCWhileCompactionScheduled) { using Store = HeapVector<Member<Object>>; Persistent<Store> persistent(MakeGarbageCollected<Store>()); - persistent->push_back(Object::Create()); + persistent->push_back(MakeGarbageCollected<Object>()); IncrementalMarkingTestDriver driver(ThreadState::Current()); HeapCompact::ScheduleCompactionGCForTesting(true); @@ -1769,7 +1760,7 @@ IncrementalMarkingTestDriver driver(ThreadState::Current()); driver.Start(); driver.FinishSteps(); - persistent->set_object(Object::Create()); + persistent->set_object(MakeGarbageCollected<Object>()); driver.FinishGC(); ConservativelyCollectGarbage(); }
diff --git a/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.cc b/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.cc index ac5f287a..758c465 100644 --- a/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.cc +++ b/third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.cc
@@ -26,8 +26,7 @@ const char* units, const String& value) { StringUTF8Adaptor adapter(value); - std::string utf8(adapter.Data(), adapter.length()); - memory_allocator_dump_->AddString(name, units, utf8); + memory_allocator_dump_->AddString(name, units, adapter.AsStdString()); } WebMemoryAllocatorDumpGuid WebMemoryAllocatorDump::Guid() const {
diff --git a/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.cc b/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.cc index a8eb0b1..f5c46937 100644 --- a/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.cc +++ b/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.cc
@@ -36,10 +36,9 @@ blink::WebMemoryAllocatorDump* WebProcessMemoryDump::CreateMemoryAllocatorDump( const String& absolute_name) { StringUTF8Adaptor adapter(absolute_name); - std::string name(adapter.Data(), adapter.length()); // Get a MemoryAllocatorDump from the base/ object. base::trace_event::MemoryAllocatorDump* memory_allocator_dump = - process_memory_dump_->CreateAllocatorDump(name); + process_memory_dump_->CreateAllocatorDump(adapter.AsStdString()); return CreateWebMemoryAllocatorDump(memory_allocator_dump); } @@ -48,11 +47,11 @@ const String& absolute_name, blink::WebMemoryAllocatorDumpGuid guid) { StringUTF8Adaptor adapter(absolute_name); - std::string name(adapter.Data(), adapter.length()); // Get a MemoryAllocatorDump from the base/ object with given guid. base::trace_event::MemoryAllocatorDump* memory_allocator_dump = process_memory_dump_->CreateAllocatorDump( - name, base::trace_event::MemoryAllocatorDumpGuid(guid)); + adapter.AsStdString(), + base::trace_event::MemoryAllocatorDumpGuid(guid)); return CreateWebMemoryAllocatorDump(memory_allocator_dump); } @@ -76,11 +75,10 @@ blink::WebMemoryAllocatorDump* WebProcessMemoryDump::GetMemoryAllocatorDump( const String& absolute_name) const { StringUTF8Adaptor adapter(absolute_name); - std::string name(adapter.Data(), adapter.length()); // Retrieve the base MemoryAllocatorDump object and then reverse lookup // its wrapper. base::trace_event::MemoryAllocatorDump* memory_allocator_dump = - process_memory_dump_->GetAllocatorDump(name); + process_memory_dump_->GetAllocatorDump(adapter.AsStdString()); if (!memory_allocator_dump) return nullptr; @@ -148,17 +146,16 @@ blink::WebMemoryAllocatorDumpGuid source, const String& target_node_name) { StringUTF8Adaptor adapter(target_node_name); - std::string target_node(adapter.Data(), adapter.length()); process_memory_dump_->AddSuballocation( - base::trace_event::MemoryAllocatorDumpGuid(source), target_node); + base::trace_event::MemoryAllocatorDumpGuid(source), + adapter.AsStdString()); } SkTraceMemoryDump* WebProcessMemoryDump::CreateDumpAdapterForSkia( const String& dump_name_prefix) { StringUTF8Adaptor adapter(dump_name_prefix); - std::string prefix(adapter.Data(), adapter.length()); sk_trace_dump_list_.push_back(std::make_unique<skia::SkiaTraceMemoryDumpImpl>( - prefix, level_of_detail_, process_memory_dump_)); + adapter.AsStdString(), level_of_detail_, process_memory_dump_)); return sk_trace_dump_list_.back().get(); }
diff --git a/third_party/blink/renderer/platform/link_hash.cc b/third_party/blink/renderer/platform/link_hash.cc index 17328c1..4a1c915 100644 --- a/third_party/blink/renderer/platform/link_hash.cc +++ b/third_party/blink/renderer/platform/link_hash.cc
@@ -46,11 +46,11 @@ StringUTF8Adaptor base_utf8(base.GetString()); if (relative.Is8Bit()) { StringUTF8Adaptor relative_utf8(relative); - return url::ResolveRelative( - base_utf8.Data(), base_utf8.length(), base.GetParsed(), - relative_utf8.Data(), relative_utf8.length(), nullptr, buffer, &parsed); + return url::ResolveRelative(base_utf8.data(), base_utf8.size(), + base.GetParsed(), relative_utf8.data(), + relative_utf8.size(), nullptr, buffer, &parsed); } - return url::ResolveRelative(base_utf8.Data(), base_utf8.length(), + return url::ResolveRelative(base_utf8.data(), base_utf8.size(), base.GetParsed(), relative.Characters16(), relative.length(), nullptr, buffer, &parsed); }
diff --git a/third_party/blink/renderer/platform/mojo/DEPS b/third_party/blink/renderer/platform/mojo/DEPS index ea09dcb..cb52188 100644 --- a/third_party/blink/renderer/platform/mojo/DEPS +++ b/third_party/blink/renderer/platform/mojo/DEPS
@@ -10,6 +10,7 @@ "+base/containers/span.h", "+base/message_loop/message_loop_current.h", "+base/observer_list.h", + "+base/strings/latin1_string_conversions.h", "+base/strings/string16.h", "+mojo/public/cpp/base/time_mojom_traits.h", "+mojo/public/cpp/bindings/binding.h",
diff --git a/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.cc b/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.cc index 1090633..a0c0200 100644 --- a/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.cc +++ b/third_party/blink/renderer/platform/mojo/big_string_mojom_traits.cc
@@ -17,9 +17,7 @@ mojo_base::BigBuffer StructTraits<mojo_base::mojom::BigStringDataView, WTF::String>::data(const WTF::String& input) { WTF::StringUTF8Adaptor adaptor(input); - return mojo_base::BigBuffer( - base::make_span(reinterpret_cast<const uint8_t*>(adaptor.Data()), - adaptor.length() * sizeof(char))); + return mojo_base::BigBuffer(base::as_bytes(base::make_span(adaptor))); } // static
diff --git a/third_party/blink/renderer/platform/mojo/string16_mojom_traits.cc b/third_party/blink/renderer/platform/mojo/string16_mojom_traits.cc index 985601f7..1c8d026 100644 --- a/third_party/blink/renderer/platform/mojo/string16_mojom_traits.cc +++ b/third_party/blink/renderer/platform/mojo/string16_mojom_traits.cc
@@ -7,48 +7,32 @@ #include <cstring> #include "base/containers/span.h" +#include "base/strings/latin1_string_conversions.h" #include "mojo/public/cpp/base/big_buffer.h" #include "mojo/public/cpp/base/big_buffer_mojom_traits.h" namespace mojo { -// static -void* StructTraits<mojo_base::mojom::String16DataView, - WTF::String>::SetUpContext(const WTF::String& input) { - // If it is null (i.e., StructTraits<>::IsNull() returns true), this method is - // guaranteed not to be called. - DCHECK(!input.IsNull()); +MaybeOwnedString16::MaybeOwnedString16(base::string16 owned_storage) + : owned_storage_(owned_storage), + unowned_(base::make_span( + reinterpret_cast<const uint16_t*>(owned_storage_.data()), + owned_storage_.size())) {} - if (!input.Is8Bit()) - return nullptr; +MaybeOwnedString16::MaybeOwnedString16(base::span<const uint16_t> unowned) + : unowned_(unowned) {} - return new base::string16(input.Characters8(), - input.Characters8() + input.length()); -} +MaybeOwnedString16::~MaybeOwnedString16() = default; // static -void StructTraits<mojo_base::mojom::String16DataView, - WTF::String>::TearDownContext(const WTF::String& input, - void* context) { - delete static_cast<base::string16*>(context); -} - -// static -base::span<const uint16_t> -StructTraits<mojo_base::mojom::String16DataView, WTF::String>::data( - const WTF::String& input, - void* context) { - auto* contextObject = static_cast<base::string16*>(context); - DCHECK_EQ(input.Is8Bit(), !!contextObject); - - if (contextObject) { - return base::make_span( - reinterpret_cast<const uint16_t*>(contextObject->data()), - contextObject->size()); +MaybeOwnedString16 StructTraits<mojo_base::mojom::String16DataView, + WTF::String>::data(const WTF::String& input) { + if (input.Is8Bit()) { + return MaybeOwnedString16(base::Latin1OrUTF16ToUTF16( + input.length(), input.Characters8(), nullptr)); } - - return base::make_span( - reinterpret_cast<const uint16_t*>(input.Characters16()), input.length()); + return MaybeOwnedString16(base::make_span( + reinterpret_cast<const uint16_t*>(input.Characters16()), input.length())); } // static
diff --git a/third_party/blink/renderer/platform/mojo/string16_mojom_traits.h b/third_party/blink/renderer/platform/mojo/string16_mojom_traits.h index 101e335..a73f44c 100644 --- a/third_party/blink/renderer/platform/mojo/string16_mojom_traits.h +++ b/third_party/blink/renderer/platform/mojo/string16_mojom_traits.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_STRING16_MOJOM_TRAITS_H_ #include "base/containers/span.h" +#include "base/logging.h" #include "base/strings/string16.h" #include "mojo/public/cpp/bindings/struct_traits.h" #include "mojo/public/mojom/base/string16.mojom-blink.h" @@ -17,17 +18,47 @@ namespace mojo { +// WTF::String stores string data as 8-bit strings if only Latin-1 characters +// are present. During Mojo serialization, this helper provides a scratch buffer +// that can be used for converting an 8-bit string to a 16-bit string. +class PLATFORM_EXPORT MaybeOwnedString16 { + public: + explicit MaybeOwnedString16(base::string16 owned_storage); + explicit MaybeOwnedString16(base::span<const uint16_t> unowned); + ~MaybeOwnedString16(); + + const uint16_t* data() const { return unowned_.data(); } + size_t size() const { return unowned_.size(); } + + private: + base::string16 owned_storage_; + base::span<const uint16_t> unowned_; +}; + +template <> +struct PLATFORM_EXPORT ArrayTraits<MaybeOwnedString16> { + using Element = const uint16_t; + + static bool IsNull(const MaybeOwnedString16&) { return false; } + static size_t GetSize(const MaybeOwnedString16& input) { + return input.size(); + } + static const Element* GetData(const MaybeOwnedString16& input) { + return input.data(); + } + static const Element& GetAt(const MaybeOwnedString16& input, size_t index) { + return input.data()[index]; + } +}; + template <> struct PLATFORM_EXPORT StructTraits<mojo_base::mojom::String16DataView, WTF::String> { static bool IsNull(const WTF::String& input) { return input.IsNull(); } static void SetToNull(WTF::String* output) { *output = WTF::String(); } - static void* SetUpContext(const WTF::String& input); - static void TearDownContext(const WTF::String& input, void* context); + static MaybeOwnedString16 data(const WTF::String& input); - static base::span<const uint16_t> data(const WTF::String& input, - void* context); static bool Read(mojo_base::mojom::String16DataView, WTF::String* out); };
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index ba6b3d8..70966b3 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -162,6 +162,7 @@ { name: "BlinkGenPropertyTrees", status: "stable", + implied_by: ["CompositeAfterPaint"], }, { name: "BlinkRuntimeCallStats",
diff --git a/third_party/blink/renderer/platform/testing/paint_test_configurations.h b/third_party/blink/renderer/platform/testing/paint_test_configurations.h index 614813a..f25b5f9 100644 --- a/third_party/blink/renderer/platform/testing/paint_test_configurations.h +++ b/third_party/blink/renderer/platform/testing/paint_test_configurations.h
@@ -37,16 +37,19 @@ #define INSTANTIATE_PAINT_TEST_SUITE_P(test_class) \ INSTANTIATE_TEST_SUITE_P( \ All, test_class, \ - ::testing::Values(0, kBlinkGenPropertyTrees, kCompositeAfterPaint)) + ::testing::Values(0, kBlinkGenPropertyTrees, \ + kBlinkGenPropertyTrees | kCompositeAfterPaint)) #define INSTANTIATE_CAP_TEST_SUITE_P(test_class) \ - INSTANTIATE_TEST_SUITE_P(All, test_class, \ - ::testing::Values(kCompositeAfterPaint)) + INSTANTIATE_TEST_SUITE_P( \ + All, test_class, \ + ::testing::Values(kBlinkGenPropertyTrees | kCompositeAfterPaint)) #define INSTANTIATE_LAYER_LIST_TEST_SUITE_P(test_class) \ INSTANTIATE_TEST_SUITE_P( \ All, test_class, \ - ::testing::Values(kBlinkGenPropertyTrees, kCompositeAfterPaint)) + ::testing::Values(kBlinkGenPropertyTrees, \ + kBlinkGenPropertyTrees | kCompositeAfterPaint)) } // namespace blink
diff --git a/third_party/blink/renderer/platform/weborigin/known_ports.cc b/third_party/blink/renderer/platform/weborigin/known_ports.cc index bd0845ce..609b35a 100644 --- a/third_party/blink/renderer/platform/weborigin/known_ports.cc +++ b/third_party/blink/renderer/platform/weborigin/known_ports.cc
@@ -79,8 +79,7 @@ if (!effective_port) effective_port = DefaultPortForProtocol(protocol); StringUTF8Adaptor utf8(protocol); - return net::IsPortAllowedForScheme(effective_port, - std::string(utf8.Data(), utf8.length())); + return net::IsPortAllowedForScheme(effective_port, utf8.AsStdString()); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/weborigin/kurl.cc b/third_party/blink/renderer/platform/weborigin/kurl.cc index b9a6a4c..8d66e1c 100644 --- a/third_party/blink/renderer/platform/weborigin/kurl.cc +++ b/third_party/blink/renderer/platform/weborigin/kurl.cc
@@ -71,7 +71,7 @@ // null character pointer since ReplaceComponents has special meaning for null. static const char* CharactersOrEmpty(const StringUTF8Adaptor& string) { static const char kZero = 0; - return string.Data() ? string.Data() : &kZero; + return string.data() ? string.data() : &kZero; } static bool IsSchemeFirstChar(char c) { @@ -430,15 +430,15 @@ // the URL and set "m_isValid." url::RawCanonOutputT<char> canon_protocol; url::Component protocol_component; - if (!url::CanonicalizeScheme(new_protocol_utf8.Data(), - url::Component(0, new_protocol_utf8.length()), + if (!url::CanonicalizeScheme(new_protocol_utf8.data(), + url::Component(0, new_protocol_utf8.size()), &canon_protocol, &protocol_component) || !protocol_component.is_nonempty()) return false; url::Replacements<char> replacements; replacements.SetScheme(CharactersOrEmpty(new_protocol_utf8), - url::Component(0, new_protocol_utf8.length())); + url::Component(0, new_protocol_utf8.size())); ReplaceComponents(replacements); // isValid could be false but we still return true here. This is because @@ -454,7 +454,7 @@ StringUTF8Adaptor host_utf8(host); url::Replacements<char> replacements; replacements.SetHost(CharactersOrEmpty(host_utf8), - url::Component(0, host_utf8.length())); + url::Component(0, host_utf8.size())); ReplaceComponents(replacements); } @@ -485,7 +485,7 @@ url::Replacements<char> replacements; StringUTF8Adaptor host_utf8(host_and_port); replacements.SetHost(CharactersOrEmpty(host_utf8), - url::Component(0, host_utf8.length())); + url::Component(0, host_utf8.size())); ReplaceComponents(replacements); return; } @@ -498,9 +498,9 @@ url::Replacements<char> replacements; replacements.SetHost(CharactersOrEmpty(host_utf8), - url::Component(0, host_utf8.length())); + url::Component(0, host_utf8.size())); replacements.SetPort(CharactersOrEmpty(port_utf8), - url::Component(0, port_utf8.length())); + url::Component(0, port_utf8.size())); ReplaceComponents(replacements); } @@ -543,7 +543,7 @@ StringUTF8Adaptor user_utf8(user); url::Replacements<char> replacements; replacements.SetUsername(CharactersOrEmpty(user_utf8), - url::Component(0, user_utf8.length())); + url::Component(0, user_utf8.size())); ReplaceComponents(replacements); } @@ -558,7 +558,7 @@ StringUTF8Adaptor pass_utf8(pass); url::Replacements<char> replacements; replacements.SetPassword(CharactersOrEmpty(pass_utf8), - url::Component(0, pass_utf8.length())); + url::Component(0, pass_utf8.size())); ReplaceComponents(replacements); } @@ -571,11 +571,12 @@ StringUTF8Adaptor fragment_utf8(fragment); url::Replacements<char> replacements; - if (fragment.IsNull()) + if (fragment.IsNull()) { replacements.ClearRef(); - else + } else { replacements.SetRef(CharactersOrEmpty(fragment_utf8), - url::Component(0, fragment_utf8.length())); + url::Component(0, fragment_utf8.size())); + } ReplaceComponents(replacements); } @@ -595,7 +596,7 @@ // WebCore expects the query string to begin with a question mark, but // GoogleURL doesn't. So we trim off the question mark when setting. replacements.SetQuery(CharactersOrEmpty(query_utf8), - url::Component(1, query_utf8.length() - 1)); + url::Component(1, query_utf8.size() - 1)); } else { // When set with the empty string or something that doesn't begin with // a question mark, KURL.cpp will add a question mark for you. The only @@ -604,7 +605,7 @@ // URL, whereas we'll clear it. // FIXME We should eliminate this difference. replacements.SetQuery(CharactersOrEmpty(query_utf8), - url::Component(0, query_utf8.length())); + url::Component(0, query_utf8.size())); } ReplaceComponents(replacements); } @@ -615,14 +616,14 @@ StringUTF8Adaptor path_utf8(path); url::Replacements<char> replacements; replacements.SetPath(CharactersOrEmpty(path_utf8), - url::Component(0, path_utf8.length())); + url::Component(0, path_utf8.size())); ReplaceComponents(replacements); } String DecodeURLEscapeSequences(const String& string, DecodeURLMode mode) { StringUTF8Adaptor string_utf8(string); url::RawCanonOutputT<base::char16> unescaped; - url::DecodeURLEscapeSequences(string_utf8.Data(), string_utf8.length(), mode, + url::DecodeURLEscapeSequences(string_utf8.data(), string_utf8.size(), mode, &unescaped); return StringImpl::Create8BitIfPossible( reinterpret_cast<UChar*>(unescaped.data()), unescaped.length()); @@ -743,12 +744,12 @@ url::RawCanonOutputT<char> output; if (!relative.IsNull() && relative.Is8Bit()) { StringUTF8Adaptor relative_utf8(relative); - is_valid_ = url::ResolveRelative(base_utf8.Data(), base_utf8.length(), - base.parsed_, relative_utf8.Data(), - clampTo<int>(relative_utf8.length()), + is_valid_ = url::ResolveRelative(base_utf8.data(), base_utf8.size(), + base.parsed_, relative_utf8.data(), + clampTo<int>(relative_utf8.size()), charset_converter, &output, &parsed_); } else { - is_valid_ = url::ResolveRelative(base_utf8.Data(), base_utf8.length(), + is_valid_ = url::ResolveRelative(base_utf8.data(), base_utf8.size(), base.parsed_, relative.Characters16(), clampTo<int>(relative.length()), charset_converter, &output, &parsed_); @@ -857,7 +858,7 @@ StringUTF8Adaptor utf8(string_); is_valid_ = - url::ReplaceComponents(utf8.Data(), utf8.length(), parsed_, replacements, + url::ReplaceComponents(utf8.data(), utf8.size(), parsed_, replacements, nullptr, &output, &new_parsed); parsed_ = new_parsed; @@ -872,7 +873,7 @@ KURL::operator GURL() const { StringUTF8Adaptor utf8(string_); - return GURL(utf8.Data(), utf8.length(), parsed_, is_valid_); + return GURL(utf8.data(), utf8.size(), parsed_, is_valid_); } bool operator==(const KURL& a, const KURL& b) { return a.GetString() == b.GetString();
diff --git a/third_party/blink/renderer/platform/weborigin/security_origin.cc b/third_party/blink/renderer/platform/weborigin/security_origin.cc index 62f6af52..9d0f811 100644 --- a/third_party/blink/renderer/platform/weborigin/security_origin.cc +++ b/third_party/blink/renderer/platform/weborigin/security_origin.cc
@@ -651,9 +651,8 @@ url::RawCanonOutputT<char> canon_output; if (host.Is8Bit()) { StringUTF8Adaptor utf8(host); - *success = - url::CanonicalizeHost(utf8.Data(), url::Component(0, utf8.length()), - &canon_output, &out_host); + *success = url::CanonicalizeHost( + utf8.data(), url::Component(0, utf8.size()), &canon_output, &out_host); } else { *success = url::CanonicalizeHost(host.Characters16(), url::Component(0, host.length()),
diff --git a/third_party/blink/renderer/platform/wtf/BUILD.gn b/third_party/blink/renderer/platform/wtf/BUILD.gn index 9d861555..f4a73898 100644 --- a/third_party/blink/renderer/platform/wtf/BUILD.gn +++ b/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -148,6 +148,7 @@ "text/string_statics.h", "text/string_to_number.cc", "text/string_to_number.h", + "text/string_utf8_adaptor.cc", "text/string_utf8_adaptor.h", "text/string_view.cc", "text/string_view.h",
diff --git a/third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.cc b/third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.cc new file mode 100644 index 0000000..9ead0694 --- /dev/null +++ b/third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.cc
@@ -0,0 +1,29 @@ +// 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/platform/wtf/text/string_utf8_adaptor.h" + +namespace WTF { + +StringUTF8Adaptor::StringUTF8Adaptor(const String& string, + UTF8ConversionMode mode) { + if (string.IsEmpty()) + return; + // Unfortunately, 8 bit WTFStrings are encoded in Latin-1 and GURL uses + // UTF-8 when processing 8 bit strings. If |relative| is entirely ASCII, we + // luck out and can avoid mallocing a new buffer to hold the UTF-8 data + // because UTF-8 and Latin-1 use the same code units for ASCII code points. + if (string.Is8Bit() && string.ContainsOnlyASCIIOrEmpty()) { + data_ = reinterpret_cast<const char*>(string.Characters8()); + size_ = string.length(); + } else { + utf8_buffer_ = string.Utf8(mode); + data_ = utf8_buffer_.data(); + size_ = utf8_buffer_.length(); + } +} + +StringUTF8Adaptor::~StringUTF8Adaptor() = default; + +} // namespace WTF
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 8babc91..de0c404 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
@@ -32,50 +32,43 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_STRING_UTF8_ADAPTOR_H_ #include "base/strings/string_piece.h" -#include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/text/cstring.h" #include "third_party/blink/renderer/platform/wtf/text/text_encoding.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" +#include "third_party/blink/renderer/platform/wtf/wtf_export.h" namespace WTF { // This class lets you get UTF-8 data out of a String without mallocing a // separate buffer to hold the data if the String happens to be 8 bit and // contain only ASCII characters. -class StringUTF8Adaptor final { +class WTF_EXPORT StringUTF8Adaptor final { DISALLOW_NEW(); public: - StringUTF8Adaptor(const String& string, - UTF8ConversionMode mode = kLenientUTF8Conversion) - : data_(nullptr), length_(0) { - if (string.IsEmpty()) - return; - // Unfortunately, 8 bit WTFStrings are encoded in Latin-1 and GURL uses - // UTF-8 when processing 8 bit strings. If |relative| is entirely ASCII, we - // luck out and can avoid mallocing a new buffer to hold the UTF-8 data - // because UTF-8 and Latin-1 use the same code units for ASCII code points. - if (string.Is8Bit() && string.ContainsOnlyASCIIOrEmpty()) { - data_ = reinterpret_cast<const char*>(string.Characters8()); - length_ = string.length(); - } else { - utf8_buffer_ = string.Utf8(mode); - data_ = utf8_buffer_.data(); - length_ = utf8_buffer_.length(); - } - } + using value_type = const char; - const char* Data() const { return data_; } - wtf_size_t length() const { return length_; } + StringUTF8Adaptor(const String& string, + UTF8ConversionMode mode = kLenientUTF8Conversion); + ~StringUTF8Adaptor(); + + const char* data() const { return data_; } + wtf_size_t size() const { return size_; } base::StringPiece AsStringPiece() const { - return base::StringPiece(data_, length_); + return base::StringPiece(data_, size_); + } + + std::string AsStdString() { + // TODO(dcheng): it might be nice to store a std::string and avoid the + // double conversion... + return std::string(data_, size_); } private: CString utf8_buffer_; - const char* data_; - wtf_size_t length_; + const char* data_ = nullptr; + wtf_size_t size_ = 0; }; } // namespace WTF
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint index 9d1b7ccb..b9137fa 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
@@ -459,6 +459,11 @@ # Other: crbug.com/935728 fast/frames/transparent-scrollbar.html [ Failure ] +# Wrong contentsOpaque for will-change: opacity layers +Bug(none) compositing/will-change/composited-layers.html [ Failure ] +# Crash on non-contiguous effect on multiple columns +Bug(none) fast/multicol/composited-layer-will-change.html [ Crash ] + Bug(none) external/wpt/css/css-masking/clip-path-svg-content/clip-path-recursion-001.svg [ Failure ] Bug(none) external/wpt/css/css-masking/clip-path-svg-content/mask-nested-clip-path-001.svg [ Failure ] Bug(none) external/wpt/css/css-masking/clip-path-svg-content/mask-nested-clip-path-002.svg [ Failure ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index 3d3cf90..1b7fca1 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -294,9 +294,6 @@ crbug.com/753080 external/wpt/css/css-transforms/transform3d-preserve3d-010.html [ WontFix ] crbug.com/753080 external/wpt/css/css-transforms/transform3d-preserve3d-013.html [ WontFix ] crbug.com/753080 external/wpt/css/css-transforms/transform3d-rotatex-perspective-003.html [ WontFix ] -crbug.com/753080 external/wpt/css/css-transforms/transform3d-scale-005.html [ WontFix ] -crbug.com/753080 external/wpt/css/css-transforms/transform3d-scale-006.html [ WontFix ] -crbug.com/753080 external/wpt/css/css-transforms/transform3d-scale-007.html [ WontFix ] crbug.com/753080 external/wpt/css/css-transforms/transform3d-sorting-002.html [ WontFix ] crbug.com/753080 external/wpt/css/css-transforms/transform3d-sorting-004.html [ WontFix ] crbug.com/753080 external/wpt/css/css-transforms/transform3d-sorting-006.html [ WontFix ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index dd06f72..1ff30eb56 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2269,6 +2269,8 @@ crbug.com/492664 external/wpt/css/css-writing-modes/ortho-htb-alongside-vrl-floats-014.xht [ Failure ] crbug.com/492664 external/wpt/css/css-writing-modes/two-levels-of-orthogonal-flows-percentage.html [ Failure ] +crbug.com/637055 fast/css/outline-offset-large.html [ Skip ] + # Either "combo" or split should run: http://testthewebforward.org/docs/css-naming.html crbug.com/410320 external/wpt/css/css-writing-modes/orthogonal-parent-shrink-to-fit-001.html [ Skip ] crbug.com/492664 external/wpt/css/css-writing-modes/text-orientation-script-001.html [ Skip ] @@ -3025,6 +3027,32 @@ crbug.com/939181 virtual/not-site-per-process/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Failure Timeout ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-090a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-046a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-091-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-048a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-092a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-096-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-048-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-003-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-091a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-002-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-090-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-092-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-095a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-049-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-041-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-040a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-097-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-001-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-045-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-082-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-096a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-044-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-004-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-085-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-097a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-040-manual.html [ Skip ] crbug.com/626703 external/wpt/html/semantics/embedded-content/media-elements/src_object_blob.html [ Timeout ] crbug.com/626703 [ Mac10.12 ] external/wpt/service-workers/service-worker/websocket.https.html [ Timeout ] crbug.com/626703 [ Mac10.12 ] external/wpt/websockets/Secure-Close-4999-reason.any.html [ Timeout ] @@ -5373,6 +5401,7 @@ crbug.com/824539 [ Android ] fast/css/first-letter-hover.html [ Failure Timeout ] crbug.com/824539 [ Android ] fast/css/first-letter-visibility.html [ Failure Timeout ] crbug.com/824539 [ Android ] fast/css/focus-ring-multiline.html [ Failure Timeout ] +crbug.com/824539 [ Android ] fast/css/font-face-default-font.html [ Timeout ] crbug.com/824539 [ Android ] fast/css/invalid-percentage-property.html [ Failure Timeout ] crbug.com/824539 [ Android ] fast/css/line-height-font-order.html [ Failure Timeout ] crbug.com/824539 [ Android ] fast/css/line-thickness-underline-strikethrough-overline.html [ Failure Timeout ]
diff --git a/third_party/blink/web_tests/compositing/squashing/dont-squash-with-scale-transform-expected.txt b/third_party/blink/web_tests/compositing/squashing/dont-squash-with-scale-transform-expected.txt deleted file mode 100644 index 3e83a81..0000000 --- a/third_party/blink/web_tests/compositing/squashing/dont-squash-with-scale-transform-expected.txt +++ /dev/null
@@ -1 +0,0 @@ -Running, 0 complete, 1 remain
diff --git a/third_party/blink/web_tests/compositing/squashing/dont-squash-with-scale-transform.html b/third_party/blink/web_tests/compositing/squashing/dont-squash-with-scale-transform.html index 9373fcb..162cab2 100644 --- a/third_party/blink/web_tests/compositing/squashing/dont-squash-with-scale-transform.html +++ b/third_party/blink/web_tests/compositing/squashing/dont-squash-with-scale-transform.html
@@ -1,5 +1,6 @@ <!DOCTYPE html> <script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <style> .scale-transform { transform: scale(0.75); @@ -12,17 +13,17 @@ <div class="scale-transform" style="position: absolute; width: 200px; height: 200px; top: 100px; left: 100px; background: lightblue"></div> <div class="translate-transform" style="position: absolute; width: 200px; height: 200px; top: 100px; left: 100px; background: lightblue"></div> <script> -if (window.testRunner) - testRunner.dumpAsText(); onload = function() { - if (window.internals) { - var layers = JSON.parse(internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_DEBUG_INFO))["layers"]; + if (!window.internals) + return; - var willChangeDIVLayer = layers[4]; - var scaleTransformDIVLayer = layers[5]; - // Both transformed layers squash together after the will-change layer. - assert_true(willChangeDIVLayer.compositingReasons[0] == "Has a will-change compositing hint"); - assert_true(scaleTransformDIVLayer.compositingReasons[0] == "Secondary layer, home for a group of squashable content"); - } + test(function() { + var layers = JSON.parse(internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_DEBUG_INFO))["layers"]; + var willChangeDIVLayer = layers[4]; + var scaleTransformDIVLayer = layers[5]; + // Both transformed layers squash together after the will-change layer. + assert_equals(willChangeDIVLayer.compositingReasons[0], "Has a will-change: transform compositing hint"); + assert_equals(scaleTransformDIVLayer.compositingReasons[0], "Secondary layer, home for a group of squashable content"); + }); }; </script>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json index 7cf3e09..e25d2ab0 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -1681,6 +1681,162 @@ {} ] ], + "css/css-text-decor/text-decoration-001-manual.html": [ + [ + "/css/css-text-decor/text-decoration-001-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-002-manual.html": [ + [ + "/css/css-text-decor/text-decoration-002-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-003-manual.html": [ + [ + "/css/css-text-decor/text-decoration-003-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-004-manual.html": [ + [ + "/css/css-text-decor/text-decoration-004-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-040-manual.html": [ + [ + "/css/css-text-decor/text-decoration-040-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-040a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-040a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-041-manual.html": [ + [ + "/css/css-text-decor/text-decoration-041-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-044-manual.html": [ + [ + "/css/css-text-decor/text-decoration-044-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-045-manual.html": [ + [ + "/css/css-text-decor/text-decoration-045-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-046a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-046a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-048-manual.html": [ + [ + "/css/css-text-decor/text-decoration-048-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-048a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-048a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-049-manual.html": [ + [ + "/css/css-text-decor/text-decoration-049-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-082-manual.html": [ + [ + "/css/css-text-decor/text-decoration-082-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-085-manual.html": [ + [ + "/css/css-text-decor/text-decoration-085-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-090-manual.html": [ + [ + "/css/css-text-decor/text-decoration-090-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-090a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-090a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-091-manual.html": [ + [ + "/css/css-text-decor/text-decoration-091-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-091a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-091a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-092-manual.html": [ + [ + "/css/css-text-decor/text-decoration-092-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-092a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-092a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-095a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-095a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-096-manual.html": [ + [ + "/css/css-text-decor/text-decoration-096-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-096a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-096a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-097-manual.html": [ + [ + "/css/css-text-decor/text-decoration-097-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-097a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-097a-manual.html", + {} + ] + ], "css/css-text-decor/text-decoration-line-014.xht": [ [ "/css/css-text-decor/text-decoration-line-014.xht", @@ -110165,6 +110321,18 @@ {} ] ], + "svg/extensibility/foreignObject/compositing-backface-visibility.html": [ + [ + "/svg/extensibility/foreignObject/compositing-backface-visibility.html", + [ + [ + "/svg/extensibility/foreignObject/compositing-backface-visibility-ref.html", + "==" + ] + ], + {} + ] + ], "svg/extensibility/foreignObject/foreign-object-margin-collapsing.html": [ [ "/svg/extensibility/foreignObject/foreign-object-margin-collapsing.html", @@ -190052,6 +190220,11 @@ {} ] ], + "svg/extensibility/foreignObject/compositing-backface-visibility-ref.html": [ + [ + {} + ] + ], "svg/extensibility/foreignObject/foreign-object-paints-before-rect-ref.html": [ [ {} @@ -236324,6 +236497,18 @@ } ] ], + "element-timing/background-image-multiple-elements.html": [ + [ + "/element-timing/background-image-multiple-elements.html", + {} + ] + ], + "element-timing/background-image-stretched.html": [ + [ + "/element-timing/background-image-stretched.html", + {} + ] + ], "element-timing/buffer-before-onload.html": [ [ "/element-timing/buffer-before-onload.html", @@ -236390,6 +236575,18 @@ {} ] ], + "element-timing/multiple-background-images.html": [ + [ + "/element-timing/multiple-background-images.html", + {} + ] + ], + "element-timing/observe-background-image.html": [ + [ + "/element-timing/observe-background-image.html", + {} + ] + ], "element-timing/observe-child-element.html": [ [ "/element-timing/observe-child-element.html", @@ -277699,6 +277896,7 @@ [ "/portals/portals-post-message.sub.html", { + "testdriver": true, "timeout": "long" } ] @@ -310963,162 +311161,6 @@ {} ] ], - "css/css-text-decor/text-decoration-001.html": [ - [ - "/css/css-text-decor/text-decoration-001.html", - {} - ] - ], - "css/css-text-decor/text-decoration-002.html": [ - [ - "/css/css-text-decor/text-decoration-002.html", - {} - ] - ], - "css/css-text-decor/text-decoration-003.html": [ - [ - "/css/css-text-decor/text-decoration-003.html", - {} - ] - ], - "css/css-text-decor/text-decoration-004.html": [ - [ - "/css/css-text-decor/text-decoration-004.html", - {} - ] - ], - "css/css-text-decor/text-decoration-040.html": [ - [ - "/css/css-text-decor/text-decoration-040.html", - {} - ] - ], - "css/css-text-decor/text-decoration-040a.html": [ - [ - "/css/css-text-decor/text-decoration-040a.html", - {} - ] - ], - "css/css-text-decor/text-decoration-041.html": [ - [ - "/css/css-text-decor/text-decoration-041.html", - {} - ] - ], - "css/css-text-decor/text-decoration-044.html": [ - [ - "/css/css-text-decor/text-decoration-044.html", - {} - ] - ], - "css/css-text-decor/text-decoration-045.html": [ - [ - "/css/css-text-decor/text-decoration-045.html", - {} - ] - ], - "css/css-text-decor/text-decoration-046a.html": [ - [ - "/css/css-text-decor/text-decoration-046a.html", - {} - ] - ], - "css/css-text-decor/text-decoration-048.html": [ - [ - "/css/css-text-decor/text-decoration-048.html", - {} - ] - ], - "css/css-text-decor/text-decoration-048a.html": [ - [ - "/css/css-text-decor/text-decoration-048a.html", - {} - ] - ], - "css/css-text-decor/text-decoration-049.html": [ - [ - "/css/css-text-decor/text-decoration-049.html", - {} - ] - ], - "css/css-text-decor/text-decoration-082.html": [ - [ - "/css/css-text-decor/text-decoration-082.html", - {} - ] - ], - "css/css-text-decor/text-decoration-085.html": [ - [ - "/css/css-text-decor/text-decoration-085.html", - {} - ] - ], - "css/css-text-decor/text-decoration-090.html": [ - [ - "/css/css-text-decor/text-decoration-090.html", - {} - ] - ], - "css/css-text-decor/text-decoration-090a.html": [ - [ - "/css/css-text-decor/text-decoration-090a.html", - {} - ] - ], - "css/css-text-decor/text-decoration-091.html": [ - [ - "/css/css-text-decor/text-decoration-091.html", - {} - ] - ], - "css/css-text-decor/text-decoration-091a.html": [ - [ - "/css/css-text-decor/text-decoration-091a.html", - {} - ] - ], - "css/css-text-decor/text-decoration-092.html": [ - [ - "/css/css-text-decor/text-decoration-092.html", - {} - ] - ], - "css/css-text-decor/text-decoration-092a.html": [ - [ - "/css/css-text-decor/text-decoration-092a.html", - {} - ] - ], - "css/css-text-decor/text-decoration-095a.html": [ - [ - "/css/css-text-decor/text-decoration-095a.html", - {} - ] - ], - "css/css-text-decor/text-decoration-096.html": [ - [ - "/css/css-text-decor/text-decoration-096.html", - {} - ] - ], - "css/css-text-decor/text-decoration-096a.html": [ - [ - "/css/css-text-decor/text-decoration-096a.html", - {} - ] - ], - "css/css-text-decor/text-decoration-097.html": [ - [ - "/css/css-text-decor/text-decoration-097.html", - {} - ] - ], - "css/css-text-decor/text-decoration-097a.html": [ - [ - "/css/css-text-decor/text-decoration-097a.html", - {} - ] - ], "css/css-text-decor/text-decoration-visibility-001.xht": [ [ "/css/css-text-decor/text-decoration-visibility-001.xht", @@ -373634,109 +373676,109 @@ "6bf79ba4527f99af740bdeca945449e8f9ed7a57", "support" ], - "css/css-text-decor/text-decoration-001.html": [ + "css/css-text-decor/text-decoration-001-manual.html": [ "9b620132697dfbf68f0d10575afaf7d902e649da", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-002.html": [ + "css/css-text-decor/text-decoration-002-manual.html": [ "71c815b34e0eb43d38456ac3ec67cf3a7f96308c", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-003.html": [ + "css/css-text-decor/text-decoration-003-manual.html": [ "ee987654bf1eab14c45393314adcc6425713c154", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-004.html": [ + "css/css-text-decor/text-decoration-004-manual.html": [ "0419d85f9625f07d439b57ebc72a422ced6a5099", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-040.html": [ + "css/css-text-decor/text-decoration-040-manual.html": [ "63b63759197870f9a0616b853a4dd58e282876b1", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-040a.html": [ + "css/css-text-decor/text-decoration-040a-manual.html": [ "90963c8db6ca41c9c962ee0f38d6153cc9e7fc2b", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-041.html": [ + "css/css-text-decor/text-decoration-041-manual.html": [ "32e0598ab4a9268fd4c2f4b48dec7bbc4632ab0b", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-044.html": [ + "css/css-text-decor/text-decoration-044-manual.html": [ "63732387f27a9bd32ee42fcf3400f4b8a22c642c", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-045.html": [ + "css/css-text-decor/text-decoration-045-manual.html": [ "e8a6904071419c0b049ed5b5aad83401e236957d", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-046a.html": [ + "css/css-text-decor/text-decoration-046a-manual.html": [ "a3d5e717e3f882ba2ce9a4bf148fd62856c73b76", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-048.html": [ + "css/css-text-decor/text-decoration-048-manual.html": [ "c9070bedb3b3450e7d2c0b2b0a76dfbdfdb8e4f2", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-048a.html": [ + "css/css-text-decor/text-decoration-048a-manual.html": [ "7d598af677e9f5be323886842560f9c04d79da8a", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-049.html": [ + "css/css-text-decor/text-decoration-049-manual.html": [ "b8fb70dcd79a50ae2a49bf705688695f66ee2a88", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-082.html": [ + "css/css-text-decor/text-decoration-082-manual.html": [ "a1d5497ad2ac01d8df295b8203a9769780317f27", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-085.html": [ + "css/css-text-decor/text-decoration-085-manual.html": [ "30522cf331fecc3eb17a43a53b1bc9aa5d63ae1d", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-090.html": [ + "css/css-text-decor/text-decoration-090-manual.html": [ "580fb98c87961670cd2c23f3d01be40477cd06db", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-090a.html": [ + "css/css-text-decor/text-decoration-090a-manual.html": [ "d9ac430079b621104da62a11fca6b0bd3d6cff57", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-091.html": [ + "css/css-text-decor/text-decoration-091-manual.html": [ "2097792f1c317daaad0f05281a3b547d3555cd3d", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-091a.html": [ + "css/css-text-decor/text-decoration-091a-manual.html": [ "ee2464c5263e1cd7eb1389d4b052bc08633a78e8", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-092.html": [ + "css/css-text-decor/text-decoration-092-manual.html": [ "5ba99f0de3b463eef56f477d5e2cfffd06f16786", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-092a.html": [ + "css/css-text-decor/text-decoration-092a-manual.html": [ "5f034b3e729955dbc4c0be3c1787745423f224ff", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-095a.html": [ + "css/css-text-decor/text-decoration-095a-manual.html": [ "dc4ae513d125b9cb065875ecd2b5155ff2169fe2", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-096.html": [ + "css/css-text-decor/text-decoration-096-manual.html": [ "b7c0dc4878b365e9009026c4f537a4312bab761c", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-096a.html": [ + "css/css-text-decor/text-decoration-096a-manual.html": [ "a1f13e57cafd437805633587bdcc1190c18fb26a", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-097.html": [ + "css/css-text-decor/text-decoration-097-manual.html": [ "4d352e4da17d515aa4426ac286ca663bd8a13834", - "visual" + "manual" ], - "css/css-text-decor/text-decoration-097a.html": [ + "css/css-text-decor/text-decoration-097a-manual.html": [ "64b3249dd6be2cf4364c3ebe62ff256a0373a29d", - "visual" + "manual" ], "css/css-text-decor/text-decoration-color-recalc.html": [ "b7cde934fcfd3c73ac351f7b9566adadad542294", @@ -409758,6 +409800,14 @@ "7cd0be939f16e8aea7b00ff2b13a06102e26cc4d", "testharness" ], + "element-timing/background-image-multiple-elements.html": [ + "669f94d6b0189ba387cf90c1b49c7d4120319673", + "testharness" + ], + "element-timing/background-image-stretched.html": [ + "8f93b43524f7b3d051af90d9807a3f30ad299ae7", + "testharness" + ], "element-timing/buffer-before-onload.html": [ "805777f29c297a22497d3e4f07b6ea462b0a0b7c", "testharness" @@ -409802,6 +409852,14 @@ "dbcad248e3aea0d148416275adeec93e20d8c267", "testharness" ], + "element-timing/multiple-background-images.html": [ + "ca349fec45f6ae4bde53dbe03de673d19d295794", + "testharness" + ], + "element-timing/observe-background-image.html": [ + "0669b4c4d83b6c2e81de94beb7db15c6ca775d1b", + "testharness" + ], "element-timing/observe-child-element.html": [ "9166a4b0e6d129c356d74da2b81a6e02c08105b6", "testharness" @@ -451039,7 +451097,7 @@ "testharness" ], "portals/portals-post-message.sub.html": [ - "9fc6f6192cfa114053ae3ae6976e1c4491f299ad", + "fe58e25180ecec148e8f5bee4d79eaa366268476", "testharness" ], "portals/portals-rendering.html": [ @@ -451115,7 +451173,7 @@ "support" ], "portals/resources/portal-post-message-cross-origin-portal.sub.html": [ - "4aca1bde6983027fc363f318f22cfaaa156dee59", + "577c10ac666536eed4ed4a62fdc4924f06a47b6f", "support" ], "portals/resources/portal-post-message-during-activate-window.html": [ @@ -451123,7 +451181,7 @@ "support" ], "portals/resources/portal-post-message-portal.html": [ - "c657894f8ac4ec83e6a3ed3fd66dbc3be3b0c985", + "539048c13f5e8c21f7bda5e7d7e1b4772efb5ded", "support" ], "portals/resources/portals-adopt-predecessor-portal.html": [ @@ -467650,6 +467708,14 @@ "120941444a4898197d6b6001f9908a6cd48b62ba", "support" ], + "svg/extensibility/foreignObject/compositing-backface-visibility-ref.html": [ + "b0f504974a552545053a1a5d7c1e55eefa527fdb", + "support" + ], + "svg/extensibility/foreignObject/compositing-backface-visibility.html": [ + "1551e25f8f9675dd5cde0dc656635656f5d33023", + "reftest" + ], "svg/extensibility/foreignObject/containing-block.html": [ "da0728c96b5d0eb81435efad329bdcc3ee4dfb26", "testharness"
diff --git a/third_party/blink/web_tests/external/wpt/common/security-features/resources/common.js b/third_party/blink/web_tests/external/wpt/common/security-features/resources/common.js index 678d2a0..8b9bd0d 100644 --- a/third_party/blink/web_tests/external/wpt/common/security-features/resources/common.js +++ b/third_party/blink/web_tests/external/wpt/common/security-features/resources/common.js
@@ -263,25 +263,43 @@ } function decodeImageData(rgba) { - var rgb = new Uint8ClampedArray(rgba.length); + let decodedBytes = new Uint8ClampedArray(rgba.length); + let decodedLength = 0; - // RGBA -> RGB. - var rgb_length = 0; - for (var i = 0; i < rgba.length; ++i) { - // Skip alpha component. - if (i % 4 == 3) - continue; + for (var i = 0; i + 12 <= rgba.length; i += 12) { + // A single byte is encoded in three pixels. 8 pixel octets (among + // 9 octets = 3 pixels * 3 channels) are used to encode 8 bits, + // the most significant bit first, where `0` and `255` in pixel values + // represent `0` and `1` in bits, respectively. + // This encoding is used to avoid errors due to different color spaces. + const bits = []; + for (let j = 0; j < 3; ++j) { + bits.push(rgba[i + j * 4 + 0]); + bits.push(rgba[i + j * 4 + 1]); + bits.push(rgba[i + j * 4 + 2]); + // rgba[i + j * 4 + 3]: Skip alpha channel. + } + // The last one element is not used. + bits.pop(); + + // Decode a single byte. + let byte = 0; + for (let j = 0; j < 8; ++j) { + byte <<= 1; + if (bits[j] >= 128) + byte |= 1; + } // Zero is the string terminator. - if (rgba[i] == 0) + if (byte == 0) break; - rgb[rgb_length++] = rgba[i]; + decodedBytes[decodedLength++] = byte; } // Remove trailing nulls from data. - rgb = rgb.subarray(0, rgb_length); - var string_data = (new TextDecoder("ascii")).decode(rgb); + decodedBytes = decodedBytes.subarray(0, decodedLength); + var string_data = (new TextDecoder("ascii")).decode(decodedBytes); return JSON.parse(string_data); }
diff --git a/third_party/blink/web_tests/external/wpt/common/security-features/subresource/image.py b/third_party/blink/web_tests/external/wpt/common/security-features/subresource/image.py index d132889..42ebc07 100644 --- a/third_party/blink/web_tests/external/wpt/common/security-features/subresource/image.py +++ b/third_party/blink/web_tests/external/wpt/common/security-features/subresource/image.py
@@ -60,20 +60,17 @@ def encode_string_as_bmp_image(string_data): data_bytes = array.array("B", string_data) + num_bytes = len(data_bytes) - # Convert data bytes to color data (RGB). + # Encode data bytes to color data (RGB), one bit per channel. + # This is to avoid errors due to different color spaces used in decoding. color_data = [] - num_components = 3 - rgb = [0] * num_components - i = 0 for byte in data_bytes: - component_index = i % num_components - rgb[component_index] = byte - if component_index == (num_components - 1) or i == (num_bytes - 1): - color_data.append(tuple(rgb)) - rgb = [0] * num_components - i += 1 + p = [int(x) * 255 for x in '{0:08b}'.format(byte)] + color_data.append((p[0], p[1], p[2])) + color_data.append((p[3], p[4], p[5])) + color_data.append((p[6], p[7], 0)) # Render image. num_pixels = len(color_data)
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-001.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-001-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-001.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-001-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-002.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-002-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-002.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-002-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-003.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-003-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-003.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-003-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-004.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-004-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-004.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-004-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-040.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-040-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-040.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-040-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-040a.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-040a-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-040a.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-040a-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-041.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-041-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-041.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-041-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-044.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-044-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-044.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-044-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-045.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-045-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-045.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-045-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-046a.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-046a-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-046a.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-046a-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-048.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-048-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-048.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-048-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-048a.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-048a-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-048a.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-048a-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-049.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-049-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-049.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-049-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-082.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-082-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-082.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-082-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-085.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-085-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-085.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-085-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-090.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-090-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-090.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-090-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-090a.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-090a-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-090a.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-090a-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-091.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-091-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-091.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-091-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-091a.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-091a-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-091a.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-091a-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-092.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-092-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-092.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-092-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-092a.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-092a-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-092a.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-092a-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-095a.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-095a-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-095a.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-095a-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-096.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-096-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-096.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-096-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-096a.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-096a-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-096a.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-096a-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-097.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-097-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-097.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-097-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-097a.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-097a-manual.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-097a.html rename to third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-097a-manual.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-001-notref.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-001-notref.html index c2bde5a..ab5ae4cb 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-001-notref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-001-notref.html
@@ -6,7 +6,8 @@ </head> <body> <div style="width: 100px; height: 100px"> - Test Text + <div style="background: blue; width: 50px; height: 50px;"></div> + <div style="background: lime; width: 50px; height: 50px; margin-left: 50px;"></div> </div> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-001-ref.html index 213d81bed..05e7b31 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-001-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-001-ref.html
@@ -7,7 +7,8 @@ </head> <body> <div style="transform: scaleX(2) scaleY(2); transform-origin: 0 0; width: 100px; height: 100px;"> - Test Text + <div style="background: blue; width: 50px; height: 50px;"></div> + <div style="background: lime; width: 50px; height: 50px; margin-left: 50px;"></div> </div> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-001.html index 36fe800..d6287818 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-001.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-001.html
@@ -14,7 +14,8 @@ </head> <body> <div style="transform: scale3D(2,2,2); transform-origin: 0 0; width: 100px; height: 100px;"> - Test Text + <div style="background: blue; width: 50px; height: 50px;"></div> + <div style="background: lime; width: 50px; height: 50px; margin-left: 50px;"></div> </div> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-002.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-002.html index 723dfc8a..a677aae 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-002.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-002.html
@@ -15,7 +15,8 @@ </head> <body> <div style="transform: rotatex(90deg) scale3D(2,1,2) rotatex(-90deg); transform-origin: 0 0; width: 100px; height: 100px;"> - Test Text + <div style="background: blue; width: 50px; height: 50px;"></div> + <div style="background: lime; width: 50px; height: 50px; margin-left: 50px;"></div> </div> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-003.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-003.html index 0bb647b..e613ba5 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-003.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-003.html
@@ -14,7 +14,8 @@ </head> <body> <div style="transform: scaleX(2) scaleY(2) scaleZ(2); transform-origin: 0 0; width: 100px; height: 100px;"> - Test Text + <div style="background: blue; width: 50px; height: 50px;"></div> + <div style="background: lime; width: 50px; height: 50px; margin-left: 50px;"></div> </div> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-004.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-004.html index f5a161c0..ed8247c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-004.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-004.html
@@ -13,7 +13,8 @@ <body> <p>Nothing should appear except this sentence.</p> <div style="transform: scale3d(2, 2, 0); transform-origin: 0 0; width: 100px; height: 100px;"> - Test Text + <div style="background: blue; width: 50px; height: 50px;"></div> + <div style="background: lime; width: 50px; height: 50px; margin-left: 50px;"></div> </div> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-005-ref.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-005-ref.html index 201300c..270e413d 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-005-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-005-ref.html
@@ -7,7 +7,8 @@ </head> <body> <div style="transform: scaleY(2); transform-origin: 0 0; width: 100px; height: 100px;"> - Test Text + <div style="background: blue; width: 50px; height: 50px;"></div> + <div style="background: lime; width: 50px; height: 50px; margin-left: 50px;"></div> </div> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-005.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-005.html index fda6f7f5..524323c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-005.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-005.html
@@ -14,7 +14,8 @@ </head> <body> <div style="transform: rotatex(90deg) scale3D(1,1,2) rotatex(-90deg); transform-origin: 0 0; width: 100px; height: 100px;"> - Test Text + <div style="background: blue; width: 50px; height: 50px;"></div> + <div style="background: lime; width: 50px; height: 50px; margin-left: 50px;"></div> </div> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-006.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-006.html index b821776..b3dd537 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-006.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-006.html
@@ -14,7 +14,8 @@ </head> <body> <div style="transform: rotatex(90deg) scaleZ(2) rotatex(-90deg); transform-origin: 0 0; width: 100px; height: 100px;"> - Test Text + <div style="background: blue; width: 50px; height: 50px;"></div> + <div style="background: lime; width: 50px; height: 50px; margin-left: 50px;"></div> </div> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-007-ref.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-007-ref.html index f476aa9..b719044 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-007-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-007-ref.html
@@ -7,7 +7,8 @@ </head> <body> <div style="transform: scaleY(-1); width: 100px; height: 100px;"> - Test Text + <div style="background: blue; width: 50px; height: 50px;"></div> + <div style="background: lime; width: 50px; height: 50px; margin-left: 50px;"></div> </div> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-007.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-007.html index e9c1997..88261b7a 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-007.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-scale-007.html
@@ -12,7 +12,8 @@ </head> <body> <div style="transform: rotatex(180deg) scaleZ(-1); width: 100px; height: 100px;"> - Test Text + <div style="background: blue; width: 50px; height: 50px;"></div> + <div style="background: lime; width: 50px; height: 50px; margin-left: 50px;"></div> </div> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_coordinates_when_locked.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_coordinates_when_locked.html index 2556e83..9dfd5e1 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_coordinates_when_locked.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerlock/pointerevent_coordinates_when_locked.html
@@ -73,15 +73,15 @@ }); var actions = new test_driver.Actions(); - actions.pointerMove(/* x = */ 0, /* y = */ 0, {origin: target}).pointerDown(); + actions.pointerMove(/* x = */ 0, /* y = */ 0, {origin: div1}).pointerDown(); - pos_x = target.getBoundingClientRect().x + target.offsetWidth / 2; - pos_y = target.getBoundingClientRect().y + target.offsetHeight / 2; + pos_x = div1.offsetWidth / 2; + pos_y = div1.offsetHeight / 2; for (var i = 0; i < 10; i++) { // Alternatively move left/right and up/down. pos_x += ((-1)**i) * i * 10; pos_y -= ((-1)**i) * i * 10; - actions.pointerMove(pos_x, pos_y); + actions.pointerMove(pos_x, pos_y, {origin: div1}); } actions.pointerUp().send(); }
diff --git a/third_party/blink/web_tests/http/tests/devtools/profiler/sampling-profiler-basic-expected.txt b/third_party/blink/web_tests/http/tests/devtools/profiler/sampling-profiler-basic-expected.txt new file mode 100644 index 0000000..9cbe4dd --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/profiler/sampling-profiler-basic-expected.txt
@@ -0,0 +1,6 @@ +Tests that the sampling heap profiler works and supports nesting. + +profile1 size is ok: true +profile2 size is ok: true +Expected error: Error: Sampling profiler is not running. +
diff --git a/third_party/blink/web_tests/http/tests/devtools/profiler/sampling-profiler-basic.js b/third_party/blink/web_tests/http/tests/devtools/profiler/sampling-profiler-basic.js new file mode 100644 index 0000000..62ccd65 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/profiler/sampling-profiler-basic.js
@@ -0,0 +1,29 @@ +// 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 the sampling heap profiler works and supports nesting.\n`); + await TestRunner.loadModule('profiler'); + + const profiler = SDK.targetManager.mainTarget().model(SDK.HeapProfilerModel); + await profiler.startSampling(); + await profiler.startSampling(); + await TestRunner.evaluateInPagePromise(`let dump = new Array(5e4).fill(42.42)`); + const profile1 = await profiler.stopSampling(); + await TestRunner.evaluateInPagePromise(`let dump2 = new Array(5e4).fill(42.42)`); + const profile2 = await profiler.stopSampling(); + + const totalSize = node => node.children.reduce((acc, c) => acc + totalSize(c), node.selfSize); + const checkValue = (expected, value) => expected * 0.8 < value && value < expected * 1.2; + TestRunner.addResult(`profile1 size is ok: ${checkValue(400e3, totalSize(profile1.head))}`); + TestRunner.addResult(`profile2 size is ok: ${checkValue(800e3, totalSize(profile2.head))}`); + + try { + await profiler.stopSampling(); + } catch (e) { + TestRunner.addResult(`Expected error: ${e}`); + } + + TestRunner.completeTest(); +})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-js/timeline-js-line-level-profile.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-js/timeline-js-line-level-profile.js index 21d6d5e6..6f6d190 100644 --- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-js/timeline-js-line-level-profile.js +++ b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-js/timeline-js-line-level-profile.js
@@ -45,10 +45,10 @@ } function frameRevealed(frame) { - var url = frame.uiSourceCode().url(); + const url = frame.uiSourceCode().url(); TestRunner.addResult(TestRunner.formatters.formatAsURL(url)); cpuProfile.nodes.forEach(n => n.callFrame.url = url); - var lineProfile = PerfUI.LineLevelProfile.Performance.instance(); + const lineProfile = self.runtime.sharedInstance(PerfUI.LineLevelProfile.Performance); lineProfile.appendCPUProfile(new SDK.CPUProfileDataModel(cpuProfile)); setTimeout(() => TestRunner.completeTest(), 0); }
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-added-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-added-expected.txt index 42a6d0d5..a5325e5 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-added-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-added-expected.txt
@@ -31,6 +31,11 @@ "backgroundColor": "#0000FF", "paintInvalidations": [ { + "object": "LayoutBlockFlow (positioned) DIV id='container'", + "rect": [0, 0, 100, 100], + "reason": "paint property change" + }, + { "object": "LayoutBlockFlow (positioned) DIV class='fixed'", "rect": [50, 50, 75, 75], "reason": "chunk appeared"
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-added-individual-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-added-individual-expected.txt index 42a6d0d5..a5325e5 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-added-individual-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-added-individual-expected.txt
@@ -31,6 +31,11 @@ "backgroundColor": "#0000FF", "paintInvalidations": [ { + "object": "LayoutBlockFlow (positioned) DIV id='container'", + "rect": [0, 0, 100, 100], + "reason": "paint property change" + }, + { "object": "LayoutBlockFlow (positioned) DIV class='fixed'", "rect": [50, 50, 75, 75], "reason": "chunk appeared"
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-removed-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-removed-expected.txt index 781ddf2..5c6af203 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-removed-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-removed-expected.txt
@@ -32,6 +32,11 @@ "backgroundColor": "#0000FF", "paintInvalidations": [ { + "object": "LayoutBlockFlow (positioned) DIV id='container'", + "rect": [0, 0, 100, 100], + "reason": "paint property change" + }, + { "object": "LayoutBlockFlow (positioned) DIV class='fixed'", "rect": [50, 50, 75, 75], "reason": "chunk disappeared"
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-removed-individual-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-removed-individual-expected.txt index e92ac21..4daecdb 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-removed-individual-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/containing-block-removed-individual-expected.txt
@@ -33,6 +33,11 @@ "backgroundColor": "#0000FF", "paintInvalidations": [ { + "object": "LayoutBlockFlow (positioned) DIV id='container'", + "rect": [0, 0, 100, 100], + "reason": "paint property change" + }, + { "object": "LayoutBlockFlow (positioned) DIV class='fixed'", "rect": [50, 50, 75, 75], "reason": "chunk disappeared"
diff --git a/third_party/blink/web_tests/virtual/disable-blink-gen-property-trees/paint/invalidation/compositing/containing-block-added-expected.txt b/third_party/blink/web_tests/virtual/disable-blink-gen-property-trees/paint/invalidation/compositing/containing-block-added-expected.txt new file mode 100644 index 0000000..42a6d0d5 --- /dev/null +++ b/third_party/blink/web_tests/virtual/disable-blink-gen-property-trees/paint/invalidation/compositing/containing-block-added-expected.txt
@@ -0,0 +1,42 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV class='fixed'", + "rect": [50, 50, 75, 75], + "reason": "chunk disappeared" + } + ] + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='container'", + "position": [200, 100], + "bounds": [125, 125], + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV class='fixed'", + "rect": [50, 50, 75, 75], + "reason": "chunk appeared" + } + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/disable-blink-gen-property-trees/paint/invalidation/compositing/containing-block-added-individual-expected.txt b/third_party/blink/web_tests/virtual/disable-blink-gen-property-trees/paint/invalidation/compositing/containing-block-added-individual-expected.txt new file mode 100644 index 0000000..42a6d0d5 --- /dev/null +++ b/third_party/blink/web_tests/virtual/disable-blink-gen-property-trees/paint/invalidation/compositing/containing-block-added-individual-expected.txt
@@ -0,0 +1,42 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV class='fixed'", + "rect": [50, 50, 75, 75], + "reason": "chunk disappeared" + } + ] + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='container'", + "position": [200, 100], + "bounds": [125, 125], + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV class='fixed'", + "rect": [50, 50, 75, 75], + "reason": "chunk appeared" + } + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/disable-blink-gen-property-trees/paint/invalidation/compositing/containing-block-removed-expected.txt b/third_party/blink/web_tests/virtual/disable-blink-gen-property-trees/paint/invalidation/compositing/containing-block-removed-expected.txt new file mode 100644 index 0000000..781ddf2 --- /dev/null +++ b/third_party/blink/web_tests/virtual/disable-blink-gen-property-trees/paint/invalidation/compositing/containing-block-removed-expected.txt
@@ -0,0 +1,43 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV class='fixed'", + "rect": [50, 50, 75, 75], + "reason": "chunk appeared" + } + ] + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='container'", + "position": [200, 100], + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV class='fixed'", + "rect": [50, 50, 75, 75], + "reason": "chunk disappeared" + } + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/disable-blink-gen-property-trees/paint/invalidation/compositing/containing-block-removed-individual-expected.txt b/third_party/blink/web_tests/virtual/disable-blink-gen-property-trees/paint/invalidation/compositing/containing-block-removed-individual-expected.txt new file mode 100644 index 0000000..e92ac21 --- /dev/null +++ b/third_party/blink/web_tests/virtual/disable-blink-gen-property-trees/paint/invalidation/compositing/containing-block-removed-individual-expected.txt
@@ -0,0 +1,44 @@ +CONSOLE MESSAGE: line 30: debug +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV class='fixed'", + "rect": [50, 50, 75, 75], + "reason": "chunk appeared" + } + ] + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='container'", + "position": [200, 100], + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV class='fixed'", + "rect": [50, 50, 75, 75], + "reason": "chunk disappeared" + } + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/webcomponentsv0-runtimeflags-disabled/http/tests/origin_trials/webexposed/README.txt b/third_party/blink/web_tests/virtual/webcomponentsv0-runtimeflags-disabled/http/tests/origin_trials/webexposed/README.txt deleted file mode 100644 index dcc64a6..0000000 --- a/third_party/blink/web_tests/virtual/webcomponentsv0-runtimeflags-disabled/http/tests/origin_trials/webexposed/README.txt +++ /dev/null
@@ -1,3 +0,0 @@ -This suite runs the tests in origin_trials/webexposed with the WebComponents V0 -features explicitly disabled: ---disable-blink-features=ShadowDOMV0,CustomElementsV0,HTMLImports
diff --git a/third_party/closure_compiler/externs/pending.js b/third_party/closure_compiler/externs/pending.js index d567fa8..0fcefd4 100644 --- a/third_party/closure_compiler/externs/pending.js +++ b/third_party/closure_compiler/externs/pending.js
@@ -10,7 +10,7 @@ /** * @see https://drafts.fxtf.org/geometry-1/#domrectreadonly - * TODO(scottchen): Remove this once it is added to Closure Compiler itself. + * TODO(dpapad): Remove this once it is added to Closure Compiler itself. */ class DOMRectReadOnly { /** @@ -77,13 +77,13 @@ * @see https://wicg.github.io/ResizeObserver/#resizeobserverentry * @typedef {{contentRect: DOMRectReadOnly, * target: Element}} - * TODO(scottchen): Remove this once it is added to Closure Compiler itself. + * TODO(dpapad): Remove this once it is added to Closure Compiler itself. */ let ResizeObserverEntry; /** * @see https://wicg.github.io/ResizeObserver/#api - * TODO(scottchen): Remove this once it is added to Closure Compiler itself. + * TODO(dpapad): Remove this once it is added to Closure Compiler itself. */ class ResizeObserver { /**
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 8b32bdc..787f99e 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -41246,6 +41246,9 @@ The item was terminated because it remained in the pipeline for more than 7 days. </int> + <int value="1175" label="INVALID_ITEM"> + The item had some invalid data, probably due to database corruption. + </int> <int value="1200" label="GET_OPERATION_MAX_ATTEMPTS_REACHED"> Exceeding maximum retries for get operation request. </int>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 28a9147..80f6971 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -83551,8 +83551,9 @@ <histogram name="PageSerialization.MhtmlGeneration.BrowserWaitForRendererTime.FrameTree" - units="ms"> + units="ms" expires_after="2020-04-01"> <owner>carlosk@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Total time the browser process waited for all render processes to save their respective frames while saving a page into MHTML. @@ -83561,8 +83562,9 @@ <histogram name="PageSerialization.MhtmlGeneration.BrowserWaitForRendererTime.SingleFrame" - units="ms"> + units="ms" expires_after="2020-04-01"> <owner>carlosk@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Time the browser process waited on a single frame to be saved by a render processes while saving a page into MHTML. @@ -83570,8 +83572,9 @@ </histogram> <histogram name="PageSerialization.MhtmlGeneration.EncodingTime.SingleFrame" - units="microseconds"> + units="ms" expires_after="2020-04-01"> <owner>carlosk@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Time taken to encode into MTHML the fully serialized contents of a frame. @@ -83586,18 +83589,21 @@ <histogram name="PageSerialization.MhtmlGeneration.FinalSaveStatus" enum="MhtmlGenerationFinalSaveStatus" expires_after="M77"> <owner>carlosk@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary>Final status of the MHTML save operation for a page.</summary> </histogram> <histogram name="PageSerialization.MhtmlGeneration.FullPageSavingTime" - units="ms"> + units="ms" expires_after="2020-04-01"> <owner>carlosk@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary>Time taken to save a page into an MHTML file.</summary> </histogram> <histogram name="PageSerialization.MhtmlGeneration.PopupOverlaySkipped" enum="BooleanSkipped" expires_after="2018-08-30"> <owner>jianli@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Recorded when the popup overlays are removed from MHTML serialization. </summary> @@ -83605,8 +83611,9 @@ <histogram name="PageSerialization.MhtmlGeneration.RendererMainThreadTime.FrameTree" - units="ms"> + units="ms" expires_after="2020-04-01"> <owner>carlosk@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Time spent by the main threads of all involved render processes while saving the frame tree of a page to MHTML. @@ -83615,8 +83622,9 @@ <histogram name="PageSerialization.MhtmlGeneration.RendererMainThreadTime.SingleFrame" - units="ms"> + units="ms" expires_after="2020-04-01"> <owner>carlosk@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Time spent by the renderer main thread while saving one frame of a page to MHTML. @@ -83625,8 +83633,9 @@ <histogram name="PageSerialization.MhtmlGeneration.RendererMainThreadTime.SlowestFrame" - units="ms"> + units="ms" expires_after="2020-04-01"> <owner>carlosk@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> The longest time taken by the main thread of a render processes to save one frame of a page being saved to MHTML. In other words this is the maximum @@ -83638,8 +83647,9 @@ <histogram name="PageSerialization.MhtmlGeneration.SerializationTime.SingleFrame" - units="microseconds"> + units="ms" expires_after="2020-04-01"> <owner>carlosk@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> Time taken to fully serialize the contents of a frame, including HTML and CSS and image resources. @@ -83647,10 +83657,14 @@ </histogram> <histogram name="PageSerialization.MhtmlGeneration.WriteToDiskTime.SingleFrame" - units="ms" expires_after="M77"> + units="ms" expires_after="2020-04-01"> <owner>carlosk@chromium.org</owner> + <owner>offline-dev@chromium.org</owner> <summary> - Time spent writing a frame's encoded MHTML data to the file on disk. + Time spent writing a frame's encoded MHTML data to the file or data pipe + handle passed to the Renderer, recorded when the writing is done and the + handle is closed. Note that when writing to a data pipe, this metric does + not precisely reflect the time taken to write the data to disk. </summary> </histogram> @@ -134086,7 +134100,7 @@ </histogram> <histogram name="WebRTC.Audio.EchoCanceller.MaxCaptureJitter" - units="frames (10 ms)" expires_after="2019-05-01"> + units="frames (10 ms)" expires_after="2020-05-01"> <owner>peah@chromium.org</owner> <owner>gustaf@chromium.org</owner> <summary> @@ -134096,7 +134110,7 @@ </histogram> <histogram name="WebRTC.Audio.EchoCanceller.MaxRenderJitter" - units="frames (10 ms)" expires_after="2019-05-01"> + units="frames (10 ms)" expires_after="2020-05-01"> <owner>peah@chromium.org</owner> <owner>gustaf@chromium.org</owner> <summary> @@ -134122,7 +134136,7 @@ </histogram> <histogram name="WebRTC.Audio.EchoCanceller.MinCaptureJitter" - units="frames (10 ms)" expires_after="2019-05-01"> + units="frames (10 ms)" expires_after="2020-05-01"> <owner>peah@chromium.org</owner> <owner>gustaf@chromium.org</owner> <summary> @@ -134132,7 +134146,7 @@ </histogram> <histogram name="WebRTC.Audio.EchoCanceller.MinRenderJitter" - units="frames (10 ms)" expires_after="2019-05-01"> + units="frames (10 ms)" expires_after="2020-05-01"> <owner>peah@chromium.org</owner> <owner>gustaf@chromium.org</owner> <summary>
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv index a400afc7..408baea 100644 --- a/tools/perf/benchmark.csv +++ b/tools/perf/benchmark.csv
@@ -7,7 +7,7 @@ blink_perf.bindings,"jbroman@chromium.org, yukishiino@chromium.org, haraken@chromium.org",Blink>Bindings,https://bit.ly/blink-perf-benchmarks, blink_perf.canvas,"aaronhk@chromium.org, fserb@chromium.org",Blink>Canvas,https://bit.ly/blink-perf-benchmarks, blink_perf.css,"futhark@chromium.org, andruud@chromium.org",Blink>CSS,https://bit.ly/blink-perf-benchmarks, -blink_perf.dom,"hayato@chromium.org, tkent@chromium.org",Blink>DOM,https://bit.ly/blink-perf-benchmarks, +blink_perf.dom,hayato@chromium.org,Blink>DOM,https://bit.ly/blink-perf-benchmarks, blink_perf.events,hayato@chromium.org,Blink>DOM,https://bit.ly/blink-perf-benchmarks, blink_perf.image_decoder,cblume@chromium.org,Internals>Images>Codecs,https://bit.ly/blink-perf-benchmarks, blink_perf.layout,eae@chromium.org,,https://bit.ly/blink-perf-benchmarks,
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py index 789cb63..679c39c 100644 --- a/tools/perf/benchmarks/blink_perf.py +++ b/tools/perf/benchmarks/blink_perf.py
@@ -434,8 +434,7 @@ page.skipped_gpus = [] return story_set -@benchmark.Info(emails=['hayato@chromium.org', - 'tkent@chromium.org'], +@benchmark.Info(emails=['hayato@chromium.org'], component='Blink>DOM', documentation_url='https://bit.ly/blink-perf-benchmarks') class BlinkPerfDOM(_BlinkPerfBenchmark):
diff --git a/ui/aura/mus/input_method_mus.cc b/ui/aura/mus/input_method_mus.cc index ad8fca7..ae0bec6d 100644 --- a/ui/aura/mus/input_method_mus.cc +++ b/ui/aura/mus/input_method_mus.cc
@@ -37,6 +37,11 @@ .Run(handled ? EventResult::HANDLED : EventResult::UNHANDLED); } +void CallKeyAckCallback(InputMethodMus::KeyAckCallback ack_callback, + EventResult result) { + std::move(ack_callback).Run(result == EventResult::HANDLED); +} + void OnDispatchKeyEventPostIME(InputMethodMus::EventResultCallback callback, bool handled, bool stopped_propagation) { @@ -106,21 +111,12 @@ connector->BindInterface(ws::mojom::kServiceName, &ime_driver_); } -ui::EventDispatchDetails InputMethodMus::DispatchKeyEvent( - ui::KeyEvent* event, - EventResultCallback ack_callback) { - DCHECK(event->type() == ui::ET_KEY_PRESSED || - event->type() == ui::ET_KEY_RELEASED); - - // If no text input client or the event is synthesized, dispatch the devent - // directly without forwarding it to the real input method. - if (!GetTextInputClient() || (event->flags() & ui::EF_IS_SYNTHESIZED)) { - return DispatchKeyEventPostIME( - event, - base::BindOnce(&OnDispatchKeyEventPostIME, std::move(ack_callback))); - } - - return SendKeyEventToInputMethod(*event, std::move(ack_callback)); +//////////////////////////////////////////////////////////////////////////////// +// InputMethodMus, ui::AsyncKeyDispatcher implementation: +void InputMethodMus::DispatchKeyEventAsync(ui::KeyEvent* event, + KeyAckCallback cb) { + ignore_result(DispatchKeyEventInternal( + event, base::BindOnce(&CallKeyAckCallback, std::move(cb)))); } //////////////////////////////////////////////////////////////////////////////// @@ -138,13 +134,17 @@ ui::EventDispatchDetails InputMethodMus::DispatchKeyEvent(ui::KeyEvent* event) { ui::EventDispatchDetails dispatch_details = - DispatchKeyEvent(event, EventResultCallback()); + DispatchKeyEventInternal(event, EventResultCallback()); // Mark the event as handled so that EventGenerator doesn't attempt to // deliver event as well. event->SetHandled(); return dispatch_details; } +ui::AsyncKeyDispatcher* InputMethodMus::GetAsyncKeyDispatcher() { + return this; +} + void InputMethodMus::OnTextInputTypeChanged(const ui::TextInputClient* client) { InputMethodBase::OnTextInputTypeChanged(client); if (!IsTextInputClientFocused(client)) @@ -204,6 +204,23 @@ input_method_->ShowVirtualKeyboardIfEnabled(); } +ui::EventDispatchDetails InputMethodMus::DispatchKeyEventInternal( + ui::KeyEvent* event, + EventResultCallback ack_callback) { + DCHECK(event->type() == ui::ET_KEY_PRESSED || + event->type() == ui::ET_KEY_RELEASED); + + // If no text input client or the event is synthesized, dispatch the devent + // directly without forwarding it to the real input method. + if (!GetTextInputClient() || (event->flags() & ui::EF_IS_SYNTHESIZED)) { + return DispatchKeyEventPostIME( + event, + base::BindOnce(&OnDispatchKeyEventPostIME, std::move(ack_callback))); + } + + return SendKeyEventToInputMethod(*event, std::move(ack_callback)); +} + ui::EventDispatchDetails InputMethodMus::SendKeyEventToInputMethod( const ui::KeyEvent& event, EventResultCallback ack_callback) {
diff --git a/ui/aura/mus/input_method_mus.h b/ui/aura/mus/input_method_mus.h index e32c3fd..c8d5ed15 100644 --- a/ui/aura/mus/input_method_mus.h +++ b/ui/aura/mus/input_method_mus.h
@@ -27,23 +27,27 @@ class InputMethodMusTestApi; class TextInputClientImpl; -class AURA_EXPORT InputMethodMus : public ui::InputMethodBase { +class AURA_EXPORT InputMethodMus : public ui::InputMethodBase, + public ui::AsyncKeyDispatcher { public: using EventResultCallback = base::OnceCallback<void(ws::mojom::EventResult)>; + using KeyAckCallback = base::OnceCallback<void(bool)>; InputMethodMus(ui::internal::InputMethodDelegate* delegate, InputMethodMusDelegate* input_method_mus_delegate); ~InputMethodMus() override; void Init(service_manager::Connector* connector); - ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event, - EventResultCallback ack_callback) - WARN_UNUSED_RESULT; + + // Overridden from ui::AsyncKeyDispatcher: + void DispatchKeyEventAsync(ui::KeyEvent* event, + KeyAckCallback ack_callback) override; // Overridden from ui::InputMethod: void OnFocus() override; void OnBlur() override; ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override; + ui::AsyncKeyDispatcher* GetAsyncKeyDispatcher() override; void OnTextInputTypeChanged(const ui::TextInputClient* client) override; void OnCaretBoundsChanged(const ui::TextInputClient* client) override; void CancelComposition(const ui::TextInputClient* client) override; @@ -55,6 +59,10 @@ friend class InputMethodMusTestApi; friend TextInputClientImpl; + ui::EventDispatchDetails DispatchKeyEventInternal( + ui::KeyEvent* event, + EventResultCallback ack_callback) WARN_UNUSED_RESULT; + // Called from DispatchKeyEvent() to call to the InputMethod. ui::EventDispatchDetails SendKeyEventToInputMethod( const ui::KeyEvent& event,
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc index c6a5c47..fdd132b 100644 --- a/ui/aura/mus/window_tree_client.cc +++ b/ui/aura/mus/window_tree_client.cc
@@ -130,6 +130,11 @@ return key == client::kModalKey; } +void DispatchKeyEventCallback(EventResultCallback cb, bool handled) { + std::move(cb).Run(handled ? ws::mojom::EventResult::HANDLED + : ws::mojom::EventResult::UNHANDLED); +} + } // namespace // static @@ -1446,8 +1451,13 @@ if (event->IsKeyEvent()) { InputMethodMus* input_method = GetWindowTreeHostMus(window)->input_method(); if (input_method) { - ignore_result(input_method->DispatchKeyEvent( - event->AsKeyEvent(), CreateEventResultCallback(event_id))); + ui::AsyncKeyDispatcher* dispatcher = + input_method->GetAsyncKeyDispatcher(); + DCHECK(dispatcher); + dispatcher->DispatchKeyEventAsync( + event->AsKeyEvent(), + base::BindOnce(DispatchKeyEventCallback, + CreateEventResultCallback(event_id))); return; } }
diff --git a/ui/base/clipboard/clipboard.cc b/ui/base/clipboard/clipboard.cc index 2634410..a34a877 100644 --- a/ui/base/clipboard/clipboard.cc +++ b/ui/base/clipboard/clipboard.cc
@@ -45,7 +45,7 @@ // This shouldn't happen. The clipboard should not already exist. NOTREACHED(); } - clipboard_map->insert(std::make_pair(id, std::move(platform_clipboard))); + clipboard_map->insert({id, std::move(platform_clipboard)}); } // static @@ -59,7 +59,7 @@ return it->second.get(); Clipboard* clipboard = Clipboard::Create(); - clipboard_map->insert(std::make_pair(id, base::WrapUnique(clipboard))); + clipboard_map->insert({id, base::WrapUnique(clipboard)}); return clipboard; }
diff --git a/ui/base/clipboard/custom_data_helper.cc b/ui/base/clipboard/custom_data_helper.cc index a20b6ed..2cb28b39 100644 --- a/ui/base/clipboard/custom_data_helper.cc +++ b/ui/base/clipboard/custom_data_helper.cc
@@ -103,7 +103,7 @@ result->clear(); return; } - auto insert_result = result->insert(std::make_pair(type, base::string16())); + auto insert_result = result->insert({type, base::string16()}); if (!iter.ReadString16(&insert_result.first->second)) { // Data is corrupt, return an empty map. result->clear();
diff --git a/ui/base/clipboard/custom_data_helper_unittest.cc b/ui/base/clipboard/custom_data_helper_unittest.cc index b5360ba..338447e 100644 --- a/ui/base/clipboard/custom_data_helper_unittest.cc +++ b/ui/base/clipboard/custom_data_helper_unittest.cc
@@ -23,9 +23,9 @@ void PrepareTestData(base::Pickle* pickle) { std::unordered_map<base::string16, base::string16> data; - data.insert(std::make_pair(ASCIIToUTF16("abc"), base::string16())); - data.insert(std::make_pair(ASCIIToUTF16("de"), ASCIIToUTF16("1"))); - data.insert(std::make_pair(ASCIIToUTF16("f"), ASCIIToUTF16("23"))); + data.insert({ASCIIToUTF16("abc"), base::string16()}); + data.insert({ASCIIToUTF16("de"), ASCIIToUTF16("1")}); + data.insert({ASCIIToUTF16("f"), ASCIIToUTF16("23")}); WriteCustomDataToPickle(data, pickle); } @@ -109,9 +109,9 @@ ReadCustomDataIntoMap(pickle.data(), pickle.size(), &result); std::unordered_map<base::string16, base::string16> expected; - expected.insert(std::make_pair(ASCIIToUTF16("abc"), base::string16())); - expected.insert(std::make_pair(ASCIIToUTF16("de"), ASCIIToUTF16("1"))); - expected.insert(std::make_pair(ASCIIToUTF16("f"), ASCIIToUTF16("23"))); + expected.insert({ASCIIToUTF16("abc"), base::string16()}); + expected.insert({ASCIIToUTF16("de"), ASCIIToUTF16("1")}); + expected.insert({ASCIIToUTF16("f"), ASCIIToUTF16("23")}); EXPECT_EQ(expected, result); }
diff --git a/ui/base/ime/chromeos/input_method_chromeos.cc b/ui/base/ime/chromeos/input_method_chromeos.cc index 3394ba7..bc94b4eb 100644 --- a/ui/base/ime/chromeos/input_method_chromeos.cc +++ b/ui/base/ime/chromeos/input_method_chromeos.cc
@@ -81,7 +81,12 @@ } } -ui::EventDispatchDetails InputMethodChromeOS::DispatchKeyEvent( +void InputMethodChromeOS::DispatchKeyEventAsync(ui::KeyEvent* event, + AckCallback ack_callback) { + ignore_result(DispatchKeyEventInternal(event, std::move(ack_callback))); +} + +ui::EventDispatchDetails InputMethodChromeOS::DispatchKeyEventInternal( ui::KeyEvent* event, AckCallback ack_callback) { ResultCallback result_callback = @@ -208,7 +213,11 @@ ui::EventDispatchDetails InputMethodChromeOS::DispatchKeyEvent( ui::KeyEvent* event) { - return DispatchKeyEvent(event, AckCallback()); + return DispatchKeyEventInternal(event, AckCallback()); +} + +AsyncKeyDispatcher* InputMethodChromeOS::GetAsyncKeyDispatcher() { + return this; } void InputMethodChromeOS::OnTextInputTypeChanged(
diff --git a/ui/base/ime/chromeos/input_method_chromeos.h b/ui/base/ime/chromeos/input_method_chromeos.h index 219f5cf..e7d968ca 100644 --- a/ui/base/ime/chromeos/input_method_chromeos.h +++ b/ui/base/ime/chromeos/input_method_chromeos.h
@@ -24,19 +24,23 @@ namespace ui { -// A ui::InputMethod implementation based on IBus. +// A ui::InputMethod implementation for ChromeOS. class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) InputMethodChromeOS - : public InputMethodBase { + : public InputMethodBase, + public AsyncKeyDispatcher { public: explicit InputMethodChromeOS(internal::InputMethodDelegate* delegate); ~InputMethodChromeOS() override; using AckCallback = base::OnceCallback<void(bool)>; - ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event, - AckCallback ack_callback); + + // Overridden from AsyncKeyDispatcher: + void DispatchKeyEventAsync(ui::KeyEvent* event, + AckCallback ack_callback) override; // Overridden from InputMethod: ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override; + AsyncKeyDispatcher* GetAsyncKeyDispatcher() override; void OnTextInputTypeChanged(const TextInputClient* client) override; void OnCaretBoundsChanged(const TextInputClient* client) override; void CancelComposition(const TextInputClient* client) override; @@ -69,6 +73,9 @@ private: class PendingKeyEvent; + ui::EventDispatchDetails DispatchKeyEventInternal(ui::KeyEvent* event, + AckCallback ack_callback); + // Asks the client to confirm current composition text. void ConfirmCompositionText();
diff --git a/ui/base/ime/chromeos/input_method_chromeos_unittest.cc b/ui/base/ime/chromeos/input_method_chromeos_unittest.cc index 59863cf..07ad8b0 100644 --- a/ui/base/ime/chromeos/input_method_chromeos_unittest.cc +++ b/ui/base/ime/chromeos/input_method_chromeos_unittest.cc
@@ -1114,10 +1114,11 @@ // should not be run immediately. bool async_callback_run = false; bool async_callback_handled_result = false; - ime_->DispatchKeyEvent(&event, base::BindLambdaForTesting([&](bool handled) { - async_callback_handled_result = handled; - async_callback_run = true; - })); + ime_->DispatchKeyEventAsync(&event, + base::BindLambdaForTesting([&](bool handled) { + async_callback_handled_result = handled; + async_callback_run = true; + })); EXPECT_FALSE(async_callback_run); ASSERT_EQ(1u, caching_input_method_delegate_->callbacks().size()); @@ -1141,10 +1142,11 @@ // should not be run immediately. bool async_callback_run = false; bool async_callback_handled_result = false; - ime_->DispatchKeyEvent(&event, base::BindLambdaForTesting([&](bool handled) { - async_callback_handled_result = handled; - async_callback_run = true; - })); + ime_->DispatchKeyEventAsync(&event, + base::BindLambdaForTesting([&](bool handled) { + async_callback_handled_result = handled; + async_callback_run = true; + })); EXPECT_FALSE(async_callback_run); ASSERT_EQ(1u, caching_input_method_delegate_->callbacks().size()); @@ -1168,10 +1170,11 @@ // should not be run immediately. bool async_callback_run = false; bool async_callback_handled_result = false; - ime_->DispatchKeyEvent(&event, base::BindLambdaForTesting([&](bool handled) { - async_callback_handled_result = handled; - async_callback_run = true; - })); + ime_->DispatchKeyEventAsync(&event, + base::BindLambdaForTesting([&](bool handled) { + async_callback_handled_result = handled; + async_callback_run = true; + })); EXPECT_FALSE(async_callback_run); ASSERT_EQ(1u, caching_input_method_delegate_->callbacks().size());
diff --git a/ui/base/ime/dummy_input_method.cc b/ui/base/ime/dummy_input_method.cc index 4e3dff4..da1fdfa 100644 --- a/ui/base/ime/dummy_input_method.cc +++ b/ui/base/ime/dummy_input_method.cc
@@ -45,6 +45,10 @@ return ui::EventDispatchDetails(); } +AsyncKeyDispatcher* DummyInputMethod::GetAsyncKeyDispatcher() { + return nullptr; +} + void DummyInputMethod::OnTextInputTypeChanged(const TextInputClient* client) { }
diff --git a/ui/base/ime/dummy_input_method.h b/ui/base/ime/dummy_input_method.h index 9865876..2702187 100644 --- a/ui/base/ime/dummy_input_method.h +++ b/ui/base/ime/dummy_input_method.h
@@ -32,6 +32,7 @@ void DetachTextInputClient(TextInputClient* client) override; TextInputClient* GetTextInputClient() const override; ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override; + AsyncKeyDispatcher* GetAsyncKeyDispatcher() override; void OnTextInputTypeChanged(const TextInputClient* client) override; void OnCaretBoundsChanged(const TextInputClient* client) override; void CancelComposition(const TextInputClient* client) override;
diff --git a/ui/base/ime/input_method.h b/ui/base/ime/input_method.h index b400ece..85eeef83 100644 --- a/ui/base/ime/input_method.h +++ b/ui/base/ime/input_method.h
@@ -28,6 +28,7 @@ class InputMethodDelegate; } // namespace internal +class AsyncKeyDispatcher; class InputMethodKeyboardController; class InputMethodObserver; class KeyEvent; @@ -107,6 +108,12 @@ virtual ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) WARN_UNUSED_RESULT = 0; + // Gets the async key dispatcher interface which is used to dispatch key + // events with a callback. Some platforms (e.g. ChromeOS) require a callback + // to dispatch the key event, so DispatchKeyEvent() doesn't match the need. + // Returns null on platforms that aren't async. + virtual AsyncKeyDispatcher* GetAsyncKeyDispatcher() = 0; + // Called by the focused client whenever its text input type is changed. // Before calling this method, the focused client must confirm or clear // existing composition text and call InputMethod::CancelComposition() when @@ -186,6 +193,16 @@ bool track_key_events_for_testing_; }; +// An interface to support dispatch key event with a callback. +// This is required on certain platforms, e.g. ChromeOS. +class AsyncKeyDispatcher { + public: + // Dispatches a key event with a callback to receive the result of whether + // the event is handled by the input method. + virtual void DispatchKeyEventAsync(ui::KeyEvent* event, + base::OnceCallback<void(bool)> cb) = 0; +}; + } // namespace ui #endif // UI_BASE_IME_INPUT_METHOD_H_
diff --git a/ui/base/ime/input_method_base.cc b/ui/base/ime/input_method_base.cc index 58502e92..b2203feb 100644 --- a/ui/base/ime/input_method_base.cc +++ b/ui/base/ime/input_method_base.cc
@@ -86,6 +86,10 @@ text_input_client_->EnsureCaretNotInRect(keyboard_bounds_); } +AsyncKeyDispatcher* InputMethodBase::GetAsyncKeyDispatcher() { + return nullptr; +} + void InputMethodBase::OnTextInputTypeChanged(const TextInputClient* client) { if (!IsTextInputClientFocused(client)) return;
diff --git a/ui/base/ime/input_method_base.h b/ui/base/ime/input_method_base.h index 368fa8f..be649f4 100644 --- a/ui/base/ime/input_method_base.h +++ b/ui/base/ime/input_method_base.h
@@ -52,6 +52,7 @@ void DetachTextInputClient(TextInputClient* client) override; TextInputClient* GetTextInputClient() const override; void SetOnScreenKeyboardBounds(const gfx::Rect& new_bounds) override; + AsyncKeyDispatcher* GetAsyncKeyDispatcher() override; // If a derived class overrides this method, it should call parent's // implementation.
diff --git a/ui/base/ime/mock_input_method.cc b/ui/base/ime/mock_input_method.cc index 04ff47b..733cd97 100644 --- a/ui/base/ime/mock_input_method.cc +++ b/ui/base/ime/mock_input_method.cc
@@ -48,6 +48,10 @@ return delegate_->DispatchKeyEventPostIME(event, base::NullCallback()); } +AsyncKeyDispatcher* MockInputMethod::GetAsyncKeyDispatcher() { + return nullptr; +} + void MockInputMethod::OnFocus() { for (InputMethodObserver& observer : observer_list_) observer.OnFocus();
diff --git a/ui/base/ime/mock_input_method.h b/ui/base/ime/mock_input_method.h index 2d72e99a..d343865f 100644 --- a/ui/base/ime/mock_input_method.h +++ b/ui/base/ime/mock_input_method.h
@@ -44,6 +44,7 @@ void DetachTextInputClient(TextInputClient* client) override; TextInputClient* GetTextInputClient() const override; ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override; + AsyncKeyDispatcher* GetAsyncKeyDispatcher() override; void OnTextInputTypeChanged(const TextInputClient* client) override; void OnCaretBoundsChanged(const TextInputClient* client) override; void CancelComposition(const TextInputClient* client) override;
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc index b94206b..696adc7 100644 --- a/ui/events/blink/input_handler_proxy.cc +++ b/ui/events/blink/input_handler_proxy.cc
@@ -264,13 +264,6 @@ const base::TimeTicks now) { ui::LatencyInfo monitored_latency_info = event_with_callback->latency_info(); - if (event_with_callback->event().GetType() == - WebInputEvent::kGestureScrollUpdate) { - monitored_latency_info.set_scroll_update_delta( - static_cast<const WebGestureEvent&>(event_with_callback->event()) - .data.scroll_update.delta_y); - } - std::unique_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor = input_handler_->CreateLatencyInfoSwapPromiseMonitor( &monitored_latency_info);
diff --git a/ui/events/blink/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc index 8fc2f90..61404a4 100644 --- a/ui/events/blink/input_handler_proxy_unittest.cc +++ b/ui/events/blink/input_handler_proxy_unittest.cc
@@ -1899,67 +1899,6 @@ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); } -TEST_F(InputHandlerProxyEventQueueTest, LatencyInfoScrollUpdateDelta) { - // Scroll on compositor. - cc::InputHandlerScrollResult scroll_result_did_scroll_; - scroll_result_did_scroll_.did_scroll = true; - - EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _)) - .WillOnce(testing::Return(kImplThreadScrollState)); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1); - EXPECT_CALL( - mock_input_handler_, - ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)))) - .WillOnce(testing::Return(scroll_result_did_scroll_)); - EXPECT_CALL(mock_input_handler_, ScrollEnd(_, true)); - - HandleGestureEvent(WebInputEvent::kGestureScrollBegin); - HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20); - HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -40); - HandleGestureEvent(WebInputEvent::kGestureScrollEnd); - input_handler_proxy_.DeliverInputForBeginFrame(); - - EXPECT_EQ(0ul, event_queue().size()); - // Should run callbacks for every original events. - EXPECT_EQ(4ul, event_disposition_recorder_.size()); - EXPECT_EQ(4ul, latency_info_recorder_.size()); - EXPECT_EQ(false, latency_info_recorder_[1].coalesced()); - EXPECT_EQ(-60, latency_info_recorder_[1].scroll_update_delta()); - - EXPECT_EQ(true, latency_info_recorder_[2].coalesced()); - EXPECT_EQ(-60, latency_info_recorder_[2].scroll_update_delta()); - - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); - - latency_info_recorder_.clear(); - - // Scroll on main thread. - cc::InputHandlerScrollResult scroll_result_did_not_scroll_; - scroll_result_did_not_scroll_.did_scroll = false; - EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _)) - .WillOnce(testing::Return(kMainThreadScrollState)); - EXPECT_CALL(mock_input_handler_, ScrollEnd(_, true)); - - HandleGestureEvent(WebInputEvent::kGestureScrollBegin); - HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20); - HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -40); - HandleGestureEvent(WebInputEvent::kGestureScrollEnd); - input_handler_proxy_.DeliverInputForBeginFrame(); - - EXPECT_EQ(0ul, event_queue().size()); - // Should run callbacks for every original events. - EXPECT_EQ(8ul, event_disposition_recorder_.size()); - EXPECT_EQ(4ul, latency_info_recorder_.size()); - - EXPECT_EQ(false, latency_info_recorder_[1].coalesced()); - EXPECT_EQ(-20, latency_info_recorder_[1].scroll_update_delta()); - - EXPECT_EQ(false, latency_info_recorder_[2].coalesced()); - EXPECT_EQ(-40, latency_info_recorder_[2].scroll_update_delta()); - - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); -} - class InputHandlerProxyMainThreadScrollingReasonTest : public InputHandlerProxyTest { public:
diff --git a/ui/gl/android/android_surface_control_compat.cc b/ui/gl/android/android_surface_control_compat.cc index 6cdf316..e6e462f 100644 --- a/ui/gl/android/android_surface_control_compat.cc +++ b/ui/gl/android/android_surface_control_compat.cc
@@ -272,6 +272,8 @@ ASurfaceTransactionStats* stats) { auto* ack_ctx = static_cast<TransactionAckCtx*>(context); auto transaction_stats = ToTransactionStats(stats); + TRACE_EVENT_ASYNC_END0("gpu,benchmark", "SurfaceControlTransaction", + ack_ctx->id); if (ack_ctx->task_runner) { ack_ctx->task_runner->PostTask( @@ -281,7 +283,6 @@ std::move(ack_ctx->callback).Run(std::move(transaction_stats)); } - TRACE_EVENT_ASYNC_END0("gpu", "SurfaceControlTransaction", ack_ctx->id); delete ack_ctx; } } // namespace @@ -430,7 +431,7 @@ } void SurfaceControl::Transaction::Apply() { - TRACE_EVENT_ASYNC_BEGIN0("gpu", "SurfaceControlTransaction", id_); + TRACE_EVENT_ASYNC_BEGIN0("gpu,benchmark", "SurfaceControlTransaction", id_); SurfaceControlMethods::Get().ASurfaceTransaction_applyFn(transaction_); }
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc index 0b132a5..9692d59 100644 --- a/ui/keyboard/keyboard_controller.cc +++ b/ui/keyboard/keyboard_controller.cc
@@ -489,10 +489,7 @@ for (KeyboardControllerObserver& observer : observer_list_) observer.OnKeyboardEnableFlagsChanged(keyboard_enable_flags_); - if (IsKeyboardEnableRequested() && !IsEnabled()) - EnableKeyboard(); - else if (!IsKeyboardEnableRequested() && IsEnabled()) - DisableKeyboard(); + UpdateKeyboardAsRequestedBy(flag); } void KeyboardController::ClearEnableFlag(mojom::KeyboardEnableFlag flag) { @@ -503,10 +500,7 @@ for (KeyboardControllerObserver& observer : observer_list_) observer.OnKeyboardEnableFlagsChanged(keyboard_enable_flags_); - if (IsKeyboardEnableRequested() && !IsEnabled()) - EnableKeyboard(); - else if (!IsKeyboardEnableRequested() && IsEnabled()) - DisableKeyboard(); + UpdateKeyboardAsRequestedBy(flag); } bool KeyboardController::IsEnableFlagSet(mojom::KeyboardEnableFlag flag) const { @@ -541,6 +535,25 @@ IsEnableFlagSet(KeyboardEnableFlag::kTouchEnabled); } +void KeyboardController::UpdateKeyboardAsRequestedBy( + mojom::KeyboardEnableFlag flag) { + if (IsKeyboardEnableRequested()) { + // Note that there are two versions of the on-screen keyboard. A full layout + // is provided for accessibility, which includes sticky modifier keys to + // enable typing of hotkeys. A compact version is used in tablet mode to + // provide a layout with larger keys to facilitate touch typing. In the + // event that the a11y keyboard is being disabled, an on-screen keyboard + // might still be enabled and a forced reset is required to pick up the + // layout change. + if (IsEnabled() && flag == mojom::KeyboardEnableFlag::kAccessibilityEnabled) + RebuildKeyboardIfEnabled(); + else + EnableKeyboard(); + } else { + DisableKeyboard(); + } +} + bool KeyboardController::IsKeyboardOverscrollEnabled() const { if (!IsEnabled()) return false;
diff --git a/ui/keyboard/keyboard_controller.h b/ui/keyboard/keyboard_controller.h index 38cf908..baf8b6a 100644 --- a/ui/keyboard/keyboard_controller.h +++ b/ui/keyboard/keyboard_controller.h
@@ -321,6 +321,10 @@ // of Set/ClearEnableFlag should cause the keyboard to be enabled. bool IsKeyboardEnableRequested() const; + // Enables or disables the keyboard based on |IsKeyboardEnableRequested|, + // as requested by |flag|. + void UpdateKeyboardAsRequestedBy(mojom::KeyboardEnableFlag flag); + // Attach the keyboard window as a child of the given parent window. // Can only be called when the keyboard is not activated. |parent| must not // have any children.
diff --git a/ui/keyboard/keyboard_util_unittest.cc b/ui/keyboard/keyboard_util_unittest.cc index df47523..00d5220 100644 --- a/ui/keyboard/keyboard_util_unittest.cc +++ b/ui/keyboard/keyboard_util_unittest.cc
@@ -12,6 +12,7 @@ #include "ui/keyboard/keyboard_ui.h" #include "ui/keyboard/keyboard_util.h" #include "ui/keyboard/test/keyboard_test_util.h" +#include "ui/keyboard/test/test_keyboard_controller_observer.h" #include "ui/keyboard/test/test_keyboard_layout_delegate.h" #include "ui/keyboard/test/test_keyboard_ui_factory.h" @@ -199,4 +200,25 @@ EXPECT_FALSE(keyboard_controller_.IsKeyboardOverscrollEnabled()); } +// See https://crbug.com/946358. +TEST_F(KeyboardUtilTest, RebuildsWhenChangingAccessibilityFlag) { + // Virtual keyboard enabled with compact layout. + keyboard::SetTouchKeyboardEnabled(true); + + keyboard::TestKeyboardControllerObserver observer; + keyboard_controller_.AddObserver(&observer); + + // Virtual keyboard should rebuild to switch to a11y layout. + keyboard::SetAccessibilityKeyboardEnabled(true); + EXPECT_EQ(1, observer.disabled_count); + EXPECT_EQ(1, observer.enabled_count); + + // Virtual keyboard should rebuild to switch back to compact layout. + keyboard::SetAccessibilityKeyboardEnabled(false); + EXPECT_EQ(2, observer.disabled_count); + EXPECT_EQ(2, observer.enabled_count); + + keyboard_controller_.RemoveObserver(&observer); +} + } // namespace keyboard
diff --git a/ui/latency/BUILD.gn b/ui/latency/BUILD.gn index 6afee94..b40ad83 100644 --- a/ui/latency/BUILD.gn +++ b/ui/latency/BUILD.gn
@@ -7,6 +7,8 @@ jumbo_source_set("latency") { sources = [ + "average_lag_tracker.cc", + "average_lag_tracker.h", "fixed_point.cc", "fixed_point.h", "frame_metrics.cc", @@ -49,6 +51,7 @@ test("latency_unittests") { sources = [ + "average_lag_tracker_unittest.cc", "fixed_point_unittest.cc", "frame_metrics_test_common.cc", "frame_metrics_test_common.h",
diff --git a/ui/latency/average_lag_tracker.cc b/ui/latency/average_lag_tracker.cc new file mode 100644 index 0000000..e1419ba --- /dev/null +++ b/ui/latency/average_lag_tracker.cc
@@ -0,0 +1,159 @@ +// 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 "ui/latency/average_lag_tracker.h" + +#include "base/metrics/histogram_functions.h" + +namespace ui { + +AverageLagTracker::AverageLagTracker() = default; + +AverageLagTracker::~AverageLagTracker() = default; + +void AverageLagTracker::AddLatencyInFrame( + const ui::LatencyInfo& latency, + base::TimeTicks gpu_swap_begin_timestamp, + const std::string& scroll_name) { + base::TimeTicks event_timestamp; + bool found_component = latency.FindLatency( + ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, + &event_timestamp); + DCHECK(found_component); + // Skip if no event timestamp. + if (!found_component) + return; + + if (scroll_name == "ScrollBegin") { + // Flush all unfinished frames. + while (!frame_lag_infos_.empty()) { + base::TimeTicks last_time = + std::max(last_event_timestamp_, last_finished_frame_time_); + frame_lag_infos_.front().lag_area += + std::abs(last_event_accumulated_delta_ - + frame_lag_infos_.front().rendered_accumulated_delta) * + (frame_lag_infos_.front().frame_time - last_time).InMillisecondsF(); + // Record UMA when it's the last item in queue. + CalculateAndReportAverageLagUma(frame_lag_infos_.size() == 1); + } + // |accumulated_lag_| should be cleared/reset. + DCHECK(accumulated_lag_ == 0); + + // Create ScrollBegin report, with report time equals to gpu swap time. + LagAreaInFrame first_frame(gpu_swap_begin_timestamp); + frame_lag_infos_.push_back(first_frame); + + // Reset fields. + last_reported_time_ = event_timestamp; + last_finished_frame_time_ = event_timestamp; + last_event_accumulated_delta_ = 0; + last_rendered_accumulated_delta_ = 0; + is_begin_ = true; + } else if (scroll_name == "ScrollUpdate" && + !last_event_timestamp_.is_null()) { + DCHECK((event_timestamp - last_event_timestamp_).InMilliseconds() >= 0); + // Pop all frames where frame_time <= event_timestamp. + while (!frame_lag_infos_.empty() && + frame_lag_infos_.front().frame_time <= event_timestamp) { + base::TimeTicks front_time = + std::max(last_event_timestamp_, last_finished_frame_time_); + base::TimeTicks back_time = frame_lag_infos_.front().frame_time; + frame_lag_infos_.front().lag_area += + LagBetween(front_time, back_time, latency, event_timestamp); + + CalculateAndReportAverageLagUma(); + } + + // Initialize a new LagAreaInFrame when current_frame_time > frame_time. + if (frame_lag_infos_.empty() || + gpu_swap_begin_timestamp > frame_lag_infos_.back().frame_time) { + LagAreaInFrame new_frame(gpu_swap_begin_timestamp, + last_rendered_accumulated_delta_); + frame_lag_infos_.push_back(new_frame); + } + + // last_frame_time <= event_timestamp < frame_time + if (!frame_lag_infos_.empty()) { + // The front element in queue (if any) must satisfy frame_time > + // event_timestamp, otherwise it would be popped in the while loop. + DCHECK(last_finished_frame_time_ <= event_timestamp && + event_timestamp <= frame_lag_infos_.front().frame_time); + base::TimeTicks front_time = + std::max(last_finished_frame_time_, last_event_timestamp_); + base::TimeTicks back_time = event_timestamp; + + frame_lag_infos_.front().lag_area += + LagBetween(front_time, back_time, latency, event_timestamp); + } + } + + last_event_timestamp_ = event_timestamp; + last_event_accumulated_delta_ += latency.scroll_update_delta(); + last_rendered_accumulated_delta_ += latency.scroll_update_delta(); +} + +float AverageLagTracker::LagBetween(base::TimeTicks front_time, + base::TimeTicks back_time, + const LatencyInfo& latency, + base::TimeTicks event_timestamp) { + // In some tests, we use const event time. return 0 to avoid divided by 0. + if (event_timestamp == last_event_timestamp_) + return 0; + + float front_delta = + (last_event_accumulated_delta_ + + (latency.scroll_update_delta() * + ((front_time - last_event_timestamp_).InMillisecondsF() / + (event_timestamp - last_event_timestamp_).InMillisecondsF()))) - + frame_lag_infos_.front().rendered_accumulated_delta; + + float back_delta = + (last_event_accumulated_delta_ + + latency.scroll_update_delta() * + + ((back_time - last_event_timestamp_).InMillisecondsF() / + (event_timestamp - last_event_timestamp_).InMillisecondsF())) - + frame_lag_infos_.front().rendered_accumulated_delta; + + // Calculate the trapezoid area. + if (front_delta * back_delta >= 0) { + return 0.5f * std::abs(front_delta + back_delta) * + (back_time - front_time).InMillisecondsF(); + } + + // Corner case that rendered_accumulated_delta is in between of front_pos + // and back_pos. + return 0.5f * + std::abs((front_delta * front_delta + back_delta * back_delta) / + (back_delta - front_delta)) * + (back_time - front_time).InMillisecondsF(); +} + +void AverageLagTracker::CalculateAndReportAverageLagUma(bool send_anyway) { + DCHECK(!frame_lag_infos_.empty()); + const LagAreaInFrame& frame_lag = frame_lag_infos_.front(); + + DCHECK(frame_lag.lag_area >= 0.f); + accumulated_lag_ += frame_lag.lag_area; + + // |send_anyway| is true when we are flush all remaining frames on next + // |ScrollBegin|. Otherwise record UMA when it's ScrollBegin, or when + // reaching the 1 second gap. + if (send_anyway || is_begin_ || + (frame_lag.frame_time - last_reported_time_).InSecondsF() >= 1.0f) { + std::string scroll_name = is_begin_ ? "ScrollBegin" : "ScrollUpdate"; + base::UmaHistogramCounts1000( + "Event.Latency." + scroll_name + ".Touch.AverageLag", + accumulated_lag_ / + (frame_lag.frame_time - last_reported_time_).InMillisecondsF()); + accumulated_lag_ = 0; + last_reported_time_ = frame_lag.frame_time; + is_begin_ = false; + } + + last_finished_frame_time_ = frame_lag.frame_time; + frame_lag_infos_.pop_front(); +} + +} // namespace ui
diff --git a/ui/latency/average_lag_tracker.h b/ui/latency/average_lag_tracker.h new file mode 100644 index 0000000..898e9e9 --- /dev/null +++ b/ui/latency/average_lag_tracker.h
@@ -0,0 +1,78 @@ +// 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 UI_LATENCY_AVERAGE_LAG_TRACKER_H_ +#define UI_LATENCY_AVERAGE_LAG_TRACKER_H_ + +#include <deque> + +#include "base/macros.h" +#include "ui/latency/latency_info.h" + +namespace ui { + +// A class for reporting AverageLag metrics. See +// https://docs.google.com/document/d/1e8NuzPblIv2B9bz01oSj40rmlse7_PHq5oFS3lqz6N4/ +class AverageLagTracker { + public: + AverageLagTracker(); + ~AverageLagTracker(); + void AddLatencyInFrame(const LatencyInfo& latency, + base::TimeTicks gpu_swap_begin_timestamp, + const std::string& scroll_name); + + private: + typedef struct LagAreaInFrame { + LagAreaInFrame(base::TimeTicks time, float rendered_pos = 0) + : frame_time(time), + rendered_accumulated_delta(rendered_pos), + lag_area(0) {} + base::TimeTicks frame_time; + float rendered_accumulated_delta; + float lag_area; + } LagAreaInFrame; + + // Calculate lag in 1 seconds intervals and report UMA. + void CalculateAndReportAverageLagUma(bool send_anyway = false); + + // Helper function to calculate lag area between |front_time| to + // |back_time|. + float LagBetween(base::TimeTicks front_time, + base::TimeTicks back_time, + const LatencyInfo& latency, + base::TimeTicks event_time); + + std::deque<LagAreaInFrame> frame_lag_infos_; + + // Last scroll event's timestamp in the sequence, reset on ScrollBegin. + base::TimeTicks last_event_timestamp_; + // Timestamp of the last frame popped from |frame_lag_infos_| queue. + base::TimeTicks last_finished_frame_time_; + + // Accumulated scroll delta for actual scroll update events. Cumulated from + // latency.scroll_update_delta(). Reset on ScrollBegin. + float last_event_accumulated_delta_; + // Accumulated scroll delta got rendered on gpu swap. Cumulated from + // latency.predicted_scroll_update_delta(). It always has same value as + // |last_event_accumulated_delta_| when scroll prediction is disabled. + float last_rendered_accumulated_delta_; + + // This keeps track of the last report_time when we report to UMA, so we can + // calculate the report's duration by current - last. Reset on ScrollBegin. + base::TimeTicks last_reported_time_; + + // True if the first element of |frame_lag_infos_| is for ScrollBegin. + // For ScrollBegin, we don't wait for the 1 second interval but record the + // UMA once the frame is finished. + bool is_begin_ = false; + + // Accumulated lag area in the 1 second intervals. + float accumulated_lag_ = 0; + + DISALLOW_COPY_AND_ASSIGN(AverageLagTracker); +}; + +} // namespace ui + +#endif // UI_LATENCY_AVERAGE_LAG_TRACKER_H_
diff --git a/ui/latency/average_lag_tracker_unittest.cc b/ui/latency/average_lag_tracker_unittest.cc new file mode 100644 index 0000000..c4c34f1 --- /dev/null +++ b/ui/latency/average_lag_tracker_unittest.cc
@@ -0,0 +1,248 @@ +// 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 "ui/latency/average_lag_tracker.h" + +#include "base/test/metrics/histogram_tester.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::Bucket; +using testing::ElementsAre; + +namespace ui { +namespace { + +class AverageLagTrackerTest : public testing::Test { + public: + AverageLagTrackerTest() { ResetHistograms(); } + + void ResetHistograms() { + histogram_tester_.reset(new base::HistogramTester()); + } + + const base::HistogramTester& histogram_tester() { return *histogram_tester_; } + + void SetUp() override { + average_lag_tracker_ = std::make_unique<AverageLagTracker>(); + } + + void SyntheticTouchScrollBeginLatencyInfo(base::TimeTicks event_time, + base::TimeTicks frame_time, + float delta) { + ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH); + touch_latency.set_scroll_update_delta(delta); + touch_latency.AddLatencyNumberWithTimestamp( + ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, + event_time, 1); + touch_latency.AddLatencyNumberWithTimestamp( + ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, event_time, + 1); + average_lag_tracker_->AddLatencyInFrame(touch_latency, frame_time, + "ScrollBegin"); + } + + void SyntheticTouchScrollUpdateLatencyInfo(base::TimeTicks event_time, + base::TimeTicks frame_time, + float delta) { + ui::LatencyInfo touch_latency(ui::SourceEventType::TOUCH); + touch_latency.set_scroll_update_delta(delta); + touch_latency.AddLatencyNumberWithTimestamp( + ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, event_time, + 1); + touch_latency.AddLatencyNumberWithTimestamp( + ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, event_time, + 1); + average_lag_tracker_->AddLatencyInFrame(touch_latency, frame_time, + "ScrollUpdate"); + } + + protected: + std::unique_ptr<AverageLagTracker> average_lag_tracker_; + + std::unique_ptr<base::HistogramTester> histogram_tester_; +}; + +base::TimeTicks MillisecondsToTimeTicks(float t_ms) { + return base::TimeTicks() + base::TimeDelta::FromMilliseconds(t_ms); +} + +// Simulate a simple situation that events at every 10ms and start at t=15ms, +// frame swaps at every 10ms too and start at t=20ms and test we record one +// UMA for ScrollUpdate in one second. +TEST_F(AverageLagTrackerTest, OneSecondInterval) { + base::TimeTicks event_time = + base::TimeTicks() + base::TimeDelta::FromMilliseconds(5); + base::TimeTicks frame_time = + base::TimeTicks() + base::TimeDelta::FromMilliseconds(10); + float scroll_delta = 10; + + // ScrollBegin + event_time += base::TimeDelta::FromMilliseconds(10); // 15ms + frame_time += base::TimeDelta::FromMilliseconds(10); // 20ms + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, scroll_delta); + + // Send 101 ScrollUpdate events to verify that there is 1 AverageLag record + // per 1 second. + const int kUpdates = 101; + for (int i = 0; i < kUpdates; i++) { + event_time += base::TimeDelta::FromMilliseconds(10); + frame_time += base::TimeDelta::FromMilliseconds(10); + // First 50 has positive delta, others negetive delta. + const int sign = (i < kUpdates / 2) ? 1 : -1; + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, + sign * scroll_delta); + } + + // ScrollBegin report_time is at 20ms, so the next ScrollUpdate report_time is + // at 1020ms. The last event_time that finish this report should be later than + // 1020ms. + EXPECT_EQ(event_time, + base::TimeTicks() + base::TimeDelta::FromMilliseconds(1025)); + EXPECT_EQ(frame_time, + base::TimeTicks() + base::TimeDelta::FromMilliseconds(1030)); + + // ScrollBegin AverageLag are the area between the event original component + // (time=15ms, delta=10px) to the frame swap time (time=20ms, expect finger + // position at delta=15px). The AverageLag scaled to 1 second is + // (0.5*(10px+15px)*5ms)/5ms = 12.5px. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollBegin.Touch.AverageLag"), + ElementsAre(Bucket(12, 1))); + // This ScrollUpdate AverageLag are calculated as the finger uniformly scroll + // 10px each frame. For scroll up/down frame, the Lag at the last frame swap + // is 5px, and Lag at this frame swap is 15px. For the one changing direction, + // the Lag is from 5 to 10 and down to 5 again. So total LagArea is 99 * 100, + // plus 75. the AverageLag in 1 second is 9.975px. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollUpdate.Touch.AverageLag"), + ElementsAre(Bucket(9, 1))); + ResetHistograms(); + + // Send another ScrollBegin to end the unfinished ScrollUpdate report. + event_time += base::TimeDelta::FromMilliseconds(10); + frame_time += base::TimeDelta::FromMilliseconds(10); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, scroll_delta); + + // The last ScrollUpdate's lag is 8.75px and truncated to 8. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollUpdate.Touch.AverageLag"), + ElementsAre(Bucket(8, 1))); +} + +// Test the case that event's frame swap time is later than next event's +// creation time. (i.e, event at t=10ms will be dispatch at t=30ms, while next +// event is at t=20ms). +TEST_F(AverageLagTrackerTest, LargerLatency) { + base::TimeTicks event_time = MillisecondsToTimeTicks(10); + base::TimeTicks frame_time = + event_time + base::TimeDelta::FromMilliseconds(20); + float scroll_delta = 10; + + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, scroll_delta); + + // Send 2 ScrollUpdate. The second one will record AverageLag.ScrollBegin as + // it's event_time is larger or equal to ScrollBegin's frame_time. + for (int i = 0; i < 2; i++) { + event_time += base::TimeDelta::FromMilliseconds(10); + frame_time = event_time + base::TimeDelta::FromMilliseconds(20); + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, scroll_delta); + } + + // ScrollBegin AveragLag are from t=10ms to t=30ms, with absolute scroll + // position from 10 to 30. The AverageLag should be: + // (0.5*(10px + 30px)*20ms/20ms) = 20px. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollBegin.Touch.AverageLag"), + ElementsAre(Bucket(20, 1))); + + // Another ScrollBegin to flush unfinished frames. + // event_time doesn't matter here because the previous frames' lag are + // compute from their frame_time. + event_time = MillisecondsToTimeTicks(1000); + frame_time = MillisecondsToTimeTicks(1000); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, scroll_delta); + // The to unfinished frames' lag are (finger_positon-rendered_position)*time, + // AverageLag is ((30px-10px)*10ms+(30px-20px)*10ms)/20ms = 15px. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollUpdate.Touch.AverageLag"), + ElementsAre(Bucket(14, 1))); +} + +// Test that multiple latency being flush in the same frame swap. +TEST_F(AverageLagTrackerTest, TwoLatencyInfoInSameFrame) { + // ScrollBegin + base::TimeTicks event_time = MillisecondsToTimeTicks(10); + base::TimeTicks frame_time = MillisecondsToTimeTicks(20); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, + -10 /* scroll_delta */); + + // ScrollUpdate with event_time >= ScrollBegin frame_time will generate + // a histogram for AverageLag.ScrollBegin. + event_time = MillisecondsToTimeTicks(20); + frame_time = MillisecondsToTimeTicks(30); + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, + -10 /* scroll_delta */); + + // Absolute position from -10 to -20. The AverageLag should be: + // (0.5*(10px + 20px)*10ms/10ms) = 15px. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollBegin.Touch.AverageLag"), + ElementsAre(Bucket(14, 1))); + + event_time = MillisecondsToTimeTicks(25); + frame_time = MillisecondsToTimeTicks(30); + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, + 5 /* scroll_delta */); + + // Another ScrollBegin to flush unfinished frames. + event_time = MillisecondsToTimeTicks(1000); + frame_time = MillisecondsToTimeTicks(1000); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, 0); + + // The ScrollUpdates are at t=20ms, finger_pos=-20px, rendered_pos=-10px, + // at t=25ms, finger_pos=-15px, rendered_pos=-10px; + // To t=30ms both events get flush. + // AverageLag is (0.5*(10px+5px)*5ms + 5px*5ms)/10ms = 6.25px + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollUpdate.Touch.AverageLag"), + ElementsAre(Bucket(6, 1))); +} + +// Test the case that switching direction causes lag at current frame +// time and previous frame time are in different direction. +TEST_F(AverageLagTrackerTest, ChangeDirectionInFrame) { + // ScrollBegin + base::TimeTicks event_time = MillisecondsToTimeTicks(10); + base::TimeTicks frame_time = MillisecondsToTimeTicks(20); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, + 10 /* scroll_delta */); + + // At t=20, lag = 10px. + event_time = MillisecondsToTimeTicks(20); + frame_time = MillisecondsToTimeTicks(30); + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, + 10 /* scroll_delta */); + + // At t=30, lag = -10px. + event_time = MillisecondsToTimeTicks(30); + frame_time = MillisecondsToTimeTicks(40); + SyntheticTouchScrollUpdateLatencyInfo(event_time, frame_time, + -20 /* scroll_delta */); + + // Another ScrollBegin to flush unfinished frames. + event_time = MillisecondsToTimeTicks(1000); + frame_time = MillisecondsToTimeTicks(1000); + SyntheticTouchScrollBeginLatencyInfo(event_time, frame_time, 0); + + // From t=20 to t=30, lag_area=2*(0.5*10px*5ms)=50px*ms. + // From t=30 to t=40, lag_area=20px*10ms=200px*ms + // AverageLag = (50+200)/20 = 12.5px. + EXPECT_THAT(histogram_tester().GetAllSamples( + "Event.Latency.ScrollUpdate.Touch.AverageLag"), + ElementsAre(Bucket(12, 1))); +} + +} // namespace +} // namespace ui
diff --git a/ui/latency/latency_tracker.cc b/ui/latency/latency_tracker.cc index d98a8e0..4c851c1 100644 --- a/ui/latency/latency_tracker.cc +++ b/ui/latency/latency_tracker.cc
@@ -260,7 +260,8 @@ (IsInertialScroll(latency) && scroll_name == "ScrollInertial")); if (!IsInertialScroll(latency) && input_modality == "Touch") - CalculateAverageLag(latency, gpu_swap_begin_timestamp, scroll_name); + average_lag_tracker_.AddLatencyInFrame(latency, gpu_swap_begin_timestamp, + scroll_name); base::TimeTicks rendering_scheduled_timestamp; bool rendering_scheduled_on_main = latency.FindLatency( @@ -343,133 +344,6 @@ gpu_swap_begin_timestamp, gpu_swap_end_timestamp); } -void LatencyTracker::CalculateAverageLag( - const ui::LatencyInfo& latency, - base::TimeTicks gpu_swap_begin_timestamp, - const std::string& scroll_name) { - base::TimeTicks event_timestamp; - bool found_component = latency.FindLatency( - ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_LAST_EVENT_COMPONENT, - &event_timestamp); - DCHECK_AND_RETURN_ON_FAIL(found_component); - - if (scroll_name == "ScrollBegin") { - // Clear both lag_reports. - ReportAverageLagUma(std::move(pending_finished_lag_report_)); - if (current_lag_report_) - current_lag_report_->report_time = last_frame_time_; - ReportAverageLagUma(std::move(current_lag_report_)); - - // Create ScrollBegin report, with report time equals to gpu swap time. - LagData new_report(scroll_name); - pending_finished_lag_report_ = std::make_unique<LagData>(scroll_name); - pending_finished_lag_report_->report_time = gpu_swap_begin_timestamp; - // For ScrollBegin, we don't have the previous time to calculate the - // interpolated area, so the lag is the area between the current event - // creation time and gpu swap begin time. - pending_finished_lag_report_->lag = - (gpu_swap_begin_timestamp - event_timestamp).InMillisecondsF() * - std::abs(latency.scroll_update_delta()); - // The next report time should be a least 1 second away from current report - // time. - next_report_time_ = pending_finished_lag_report_->report_time + - base::TimeDelta::FromSeconds(1); - // Reset last_reported_time to event time. - last_reported_time_ = event_timestamp; - } else if (scroll_name == "ScrollUpdate" && - !last_event_timestamp_.is_null()) { - DCHECK((event_timestamp - last_event_timestamp_).InMilliseconds() >= 0); - - // |pending_finger_move_lag| is the interpolated area between last event to - // current event. We assume the finger moved at a constant velocity between - // the past two events, so the lag in this duration is calculated by the - // average delta(current delta/2). - float pending_finger_move_lag = - (event_timestamp - last_event_timestamp_).InMillisecondsF() * - std::abs(latency.scroll_update_delta() / 2); - - // |event_dispatch_lag| is the area between the current event creation time - // (i.e. last coalesced event of current event creation time) and gpu swap - // begin time of this event. - float event_dispatch_lag = - (gpu_swap_begin_timestamp - event_timestamp).InMillisecondsF() * - std::abs(latency.scroll_update_delta()); - - if (pending_finished_lag_report_) { - if (event_timestamp >= pending_finished_lag_report_->report_time) { - DCHECK_GE(pending_finished_lag_report_->report_time, - last_event_timestamp_); - // This event is created after this report's report time, so part of - // the |pending_finger_move_lag| should be counted in this report, the - // rest should be count in the following report. The area of first part - // is calculated by similar triangle area. - float ratio = - (pending_finished_lag_report_->report_time - last_event_timestamp_) - .InMillisecondsF() / - (event_timestamp - last_event_timestamp_).InMillisecondsF(); - pending_finished_lag_report_->lag += - pending_finger_move_lag * ratio * ratio; - pending_finger_move_lag *= 1 - ratio * ratio; - ReportAverageLagUma(std::move(pending_finished_lag_report_)); - } else { // event_timestamp < pending_finished_lag_report_->report_time - DCHECK_LE(pending_finished_lag_report_->report_time, - gpu_swap_begin_timestamp); - // This event is created before this report's report_time, so - // |pending_finger_move_lag|, and also part of |event_dispatch_lag| that - // before |report_time| should be counted in this report. - float lag_after_report_time = - (gpu_swap_begin_timestamp - - pending_finished_lag_report_->report_time) - .InMillisecondsF() * - std::abs(latency.scroll_update_delta()); - pending_finished_lag_report_->lag += pending_finger_move_lag + - event_dispatch_lag - - lag_after_report_time; - pending_finger_move_lag = 0; - event_dispatch_lag = lag_after_report_time; - } - } - - // Remaining pending lag should be counted in the |current_lag_report_|. - if (pending_finger_move_lag + event_dispatch_lag != 0) { - if (!current_lag_report_) - current_lag_report_ = std::make_unique<LagData>(scroll_name); - - current_lag_report_->lag += pending_finger_move_lag + event_dispatch_lag; - - // When the |pending_finished_lag_report_| is finished, and the current - // gpu_swap_time is larger than the |next_report_time_|, it means the we - // reach the 1 second gap, and we can filled in the timestamp and move it - // to |pending_finished_lag_report_|. We use the - // current|gpu_swap_begin_timestamp| as the report_time, so it can be - // align with gpu swaps. - if (!pending_finished_lag_report_ && - gpu_swap_begin_timestamp >= next_report_time_) { - current_lag_report_->report_time = gpu_swap_begin_timestamp; - // The next report time is 1 second away from this report time. - next_report_time_ = - gpu_swap_begin_timestamp + base::TimeDelta::FromSeconds(1); - pending_finished_lag_report_ = std::move(current_lag_report_); - } - } - } - last_event_timestamp_ = event_timestamp; - last_frame_time_ = gpu_swap_begin_timestamp; -} - -void LatencyTracker::ReportAverageLagUma(std::unique_ptr<LagData> report) { - if (report) { - DCHECK(!report->report_time.is_null()); - DCHECK(report->lag >= 0.f); - base::UmaHistogramCounts1000( - "Event.Latency." + report->scroll_name + ".Touch.AverageLag", - report->lag / - (report->report_time - last_reported_time_).InMillisecondsF()); - - last_reported_time_ = report->report_time; - } -} - // static void LatencyTracker::SetLatencyInfoProcessorForTesting( const LatencyInfoProcessor& processor) {
diff --git a/ui/latency/latency_tracker.h b/ui/latency/latency_tracker.h index d7ac971..02ecf72 100644 --- a/ui/latency/latency_tracker.h +++ b/ui/latency/latency_tracker.h
@@ -5,8 +5,8 @@ #ifndef UI_LATENCY_LATENCY_TRACKER_H_ #define UI_LATENCY_LATENCY_TRACKER_H_ -#include <deque> #include "base/macros.h" +#include "ui/latency/average_lag_tracker.h" #include "ui/latency/latency_info.h" namespace ui { @@ -52,41 +52,7 @@ base::TimeTicks gpu_swap_end_timestamp, const LatencyInfo& latency); - void CalculateAverageLag(const ui::LatencyInfo& latency, - base::TimeTicks gpu_swap_begin_timestamp, - const std::string& scroll_name); - - // Used for reporting AverageLag metrics. - typedef struct LagData { - LagData(const std::string& name) - : report_time(base::TimeTicks()), lag(0), scroll_name(name) {} - // Lag report's report_time, align with |gpu_swap_begin_time|. It should has - // one second gap between previous report. We do not set the report_time - // before the 1 second gap is reached. - base::TimeTicks report_time; - float lag; - const std::string scroll_name; - } LagData; - - void ReportAverageLagUma(std::unique_ptr<LagData> report); - - // Last scroll event's timestamp in the sequence, reset on ScrollBegin. - base::TimeTicks last_event_timestamp_; - // next_report_time is always 1 second after the newest report's report_time. - base::TimeTicks next_report_time_; - // This keeps track the last report_time when we report to UMA, so we can - // calculate the report's duration by current - last. Reset on ScrollBegin. - base::TimeTicks last_reported_time_; - // Keeps track of last gpu_swap time, so we can end the previous unfinished - // report on the new ScrollBegin. - base::TimeTicks last_frame_time_; - // Lag report that already filled in the report_time, and it will be finished - // and report once we have an event whose timestamp is later then the - // report_time. - std::unique_ptr<LagData> pending_finished_lag_report_; - // The current unfinished lag report, which doesn't reach the 1 second length - // yet. It's report_time is null and invalid now. - std::unique_ptr<LagData> current_lag_report_; + AverageLagTracker average_lag_tracker_; DISALLOW_COPY_AND_ASSIGN(LatencyTracker); };
diff --git a/ui/message_center/OWNERS b/ui/message_center/OWNERS index 806bac8..0bd96e9 100644 --- a/ui/message_center/OWNERS +++ b/ui/message_center/OWNERS
@@ -3,5 +3,6 @@ peter@chromium.org stevenjb@chromium.org yoshiki@chromium.org +tengs@chromium.org # COMPONENT: UI>Notifications
diff --git a/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc b/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc index 761a10c..7385a97 100644 --- a/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc +++ b/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
@@ -286,7 +286,7 @@ const int hit; } kTestCases[] = { #if defined(OS_WIN) - {0, is_aero_glass_enabled ? HTTRANSPARENT : HTNOWHERE}, + {0, is_aero_glass_enabled ? HTTRANSPARENT : HTCAPTION}, #else {0, HTTRANSPARENT}, #endif
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc index 3828c02..a6a60190 100644 --- a/ui/views/bubble/bubble_frame_view.cc +++ b/ui/views/bubble/bubble_frame_view.cc
@@ -181,19 +181,6 @@ if (close_->visible() && close_->GetMirroredBounds().Contains(point)) return HTCLOSE; - // Allow dialogs to show the system menu and be dragged. - if (GetWidget()->widget_delegate()->AsDialogDelegate() && - !GetWidget()->widget_delegate()->AsBubbleDialogDelegate()) { - gfx::Rect bounds(GetContentsBounds()); - bounds.Inset(title_margins_); - gfx::Rect sys_rect(0, 0, bounds.x(), bounds.y()); - sys_rect.set_origin(gfx::Point(GetMirroredXForRect(sys_rect), 0)); - if (sys_rect.Contains(point)) - return HTSYSMENU; - if (point.y() < title()->bounds().bottom()) - return HTCAPTION; - } - // Convert to RRectF to accurately represent the rounded corners of the // dialog and allow events to pass through the shadows. gfx::RRectF round_contents_bounds(gfx::RectF(GetContentsBounds()), @@ -204,6 +191,16 @@ if (!round_contents_bounds.Contains(rectf_point)) return HTTRANSPARENT; + if (HasTitle() && point.y() < title()->bounds().bottom()) { + auto* dialog_delegate = GetWidget()->widget_delegate()->AsDialogDelegate(); + // Allow the dialog to be dragged if it is not modal. This can happen if the + // dialog has no parent browser window. + if (dialog_delegate && + dialog_delegate->GetModalType() == ui::MODAL_TYPE_NONE) { + return HTCAPTION; + } + } + return GetWidget()->client_view()->NonClientHitTest(point); }
diff --git a/ui/views/window/dialog_delegate_unittest.cc b/ui/views/window/dialog_delegate_unittest.cc index b8e92a1..8aa6955 100644 --- a/ui/views/window/dialog_delegate_unittest.cc +++ b/ui/views/window/dialog_delegate_unittest.cc
@@ -98,6 +98,13 @@ views::Textfield* input() { return input_; } + ui::ModalType GetModalType() const override { + return modal_type_none_ ? ui::MODAL_TYPE_NONE : ui::MODAL_TYPE_WINDOW; + } + void set_modal_type_none(bool modal_type_none) { + modal_type_none_ = modal_type_none; + } + private: views::Textfield* input_; bool canceled_ = false; @@ -109,6 +116,7 @@ bool show_close_button_ = true; bool should_handle_escape_ = false; int dialog_buttons_ = ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL; + bool modal_type_none_ = false; DISALLOW_COPY_AND_ASSIGN(TestDialog); }; @@ -216,22 +224,22 @@ const NonClientView* view = dialog()->GetWidget()->non_client_view(); BubbleFrameView* frame = static_cast<BubbleFrameView*>(view->frame_view()); - struct { + constexpr struct { const int point; const int hit; - } cases[] = { - {0, HTSYSMENU}, - {10, HTSYSMENU}, + } kCases[] = { + {0, HTTRANSPARENT}, + {10, HTNOWHERE}, {20, HTNOWHERE}, {50, HTCLIENT /* Space is reserved for the close button. */}, {60, HTCLIENT}, {1000, HTNOWHERE}, }; - for (size_t i = 0; i < base::size(cases); ++i) { - gfx::Point point(cases[i].point, cases[i].point); - EXPECT_EQ(cases[i].hit, frame->NonClientHitTest(point)) - << " case " << i << " at point " << cases[i].point; + for (const auto test_case : kCases) { + gfx::Point point(test_case.point, test_case.point); + EXPECT_EQ(test_case.hit, frame->NonClientHitTest(point)) + << " at point " << test_case.point; } } @@ -243,18 +251,18 @@ const NonClientView* view = dialog()->GetWidget()->non_client_view(); BubbleFrameView* frame = static_cast<BubbleFrameView*>(view->frame_view()); - struct { + constexpr struct { const int point; const int hit; - } cases[] = { - {0, HTSYSMENU}, {10, HTSYSMENU}, {20, HTCLIENT}, - {50, HTCLIENT}, {60, HTCLIENT}, {1000, HTNOWHERE}, + } kCases[] = { + {0, HTTRANSPARENT}, {10, HTCLIENT}, {20, HTCLIENT}, + {50, HTCLIENT}, {60, HTCLIENT}, {1000, HTNOWHERE}, }; - for (size_t i = 0; i < base::size(cases); ++i) { - gfx::Point point(cases[i].point, cases[i].point); - EXPECT_EQ(cases[i].hit, frame->NonClientHitTest(point)) - << " case " << i << " at point " << cases[i].point; + for (const auto test_case : kCases) { + gfx::Point point(test_case.point, test_case.point); + EXPECT_EQ(test_case.hit, frame->NonClientHitTest(point)) + << " at point " << test_case.point; } } @@ -266,18 +274,43 @@ dialog()->GetWidget()->LayoutRootViewIfNecessary(); BubbleFrameView* frame = static_cast<BubbleFrameView*>(view->frame_view()); - struct { + constexpr struct { const int point; const int hit; - } cases[] = { - {0, HTSYSMENU}, {10, HTSYSMENU}, {20, HTCAPTION}, - {50, HTCLIENT}, {60, HTCLIENT}, {1000, HTNOWHERE}, + } kCases[] = { + {0, HTTRANSPARENT}, {10, HTNOWHERE}, {20, HTNOWHERE}, + {50, HTCLIENT}, {60, HTCLIENT}, {1000, HTNOWHERE}, }; - for (size_t i = 0; i < base::size(cases); ++i) { - gfx::Point point(cases[i].point, cases[i].point); - EXPECT_EQ(cases[i].hit, frame->NonClientHitTest(point)) - << " at point " << cases[i].point; + for (const auto test_case : kCases) { + gfx::Point point(test_case.point, test_case.point); + EXPECT_EQ(test_case.hit, frame->NonClientHitTest(point)) + << " at point " << test_case.point; + } +} + +TEST_F(DialogTest, HitTest_ModalTypeNone_WithTitle) { + // Ensure that BubbleFrameView hit-tests as expected when the title is shown + // and the modal type is none. + const NonClientView* view = dialog()->GetWidget()->non_client_view(); + dialog()->set_title(base::ASCIIToUTF16("Title")); + dialog()->GetWidget()->UpdateWindowTitle(); + dialog()->set_modal_type_none(true); + dialog()->GetWidget()->LayoutRootViewIfNecessary(); + BubbleFrameView* frame = static_cast<BubbleFrameView*>(view->frame_view()); + + constexpr struct { + const int point; + const int hit; + } kCases[] = { + {0, HTTRANSPARENT}, {10, HTCAPTION}, {20, HTCAPTION}, + {50, HTCLIENT}, {60, HTCLIENT}, {1000, HTNOWHERE}, + }; + + for (const auto test_case : kCases) { + gfx::Point point(test_case.point, test_case.point); + EXPECT_EQ(test_case.hit, frame->NonClientHitTest(point)) + << " at point " << test_case.point; } }
diff --git a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js index 8d400af..3f6a80f 100644 --- a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js +++ b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
@@ -286,8 +286,6 @@ * @private */ onMouseover_: function(e) { - // TODO(scottchen): Using "focus" to determine selected item might mess - // with screen readers in some edge cases. let i = 0; let target; do {
diff --git a/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.js b/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.js index 44f67b9..b3a5d49 100644 --- a/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.js +++ b/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.js
@@ -4,7 +4,7 @@ (function() { /** - * TODO(scottchen): shim for not having Animation.finished implemented. Can + * TODO(dpapad): shim for not having Animation.finished implemented. Can * replace with Animation.finished if Chrome implements it (see: * crbug.com/257235). * @param {!Animation} animation @@ -80,7 +80,7 @@ const animationFunction = viewAnimations.get(animation); assert(animationFunction); - let effectiveView = view.matches('cr-lazy-render') ? view.get() : view; + const effectiveView = view.matches('cr-lazy-render') ? view.get() : view; effectiveView.classList.add('active'); effectiveView.dispatchEvent(
diff --git a/ui/webui/resources/cr_elements/shared_vars_css.html b/ui/webui/resources/cr_elements/shared_vars_css.html index e1a0627..301e373 100644 --- a/ui/webui/resources/cr_elements/shared_vars_css.html +++ b/ui/webui/resources/cr_elements/shared_vars_css.html
@@ -163,7 +163,7 @@ font-weight: 400; } - /* TODO (scottchen): re-implement with paddings instead; */ + /* TODO (johntlee): re-implement with paddings instead; */ /* These are used for row items such as radio buttons, check boxes, list * items etc. */ --cr-section-min-height: 48px;