diff --git a/BUILD.gn b/BUILD.gn index 8942c1a..e1f9e9f3 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -962,10 +962,6 @@ } } -# Add a dummy target for compatibility w/ GYP -group("chromium_swarm_tests") { -} - group("chromium_builder_perf") { testonly = true
diff --git a/DEPS b/DEPS index ac951056..fe1289d 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,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': '0f5505bfa2c5c069b5279745bb64a6e3e9f4d15a', + 'skia_revision': '95db9b3cb1286e2c88e12035fd96fd047ea3582d', # 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': 'c9164210bdabe2ea30e88d813f95de60ab4bd164', + 'v8_revision': '35e8c7b52802e62281d3c2b5e6c8694a54f7cdc0', # 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. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'bd456561faf7de2d2756a350a9be0d10ce47c51c', + 'pdfium_revision': '78fc9aa402409f3fcd8dc1f458e67798cb3b483e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -96,7 +96,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': '33a9271eb3cf5caf925293ec6a4b47c94f1ac968', + 'catapult_revision': 'f216fdb54fb040af4fa707af64bd0c8d345af121', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -211,7 +211,7 @@ Var('chromium_git') + '/webm/libvpx.git' + '@' + 'c22b17dcefe05981918e4b7d0b6527c27e9ceda8', 'src/third_party/ffmpeg': - Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'bcaa2585874573d486d94101e883cd2e5dfbca97', + Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + 'dbbdb1680bd8e77ea72f8e5a79a09101bd7a9bdd', 'src/third_party/usrsctp/usrsctplib': Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + 'f4819e1b177f7bfdd761c147f5a649b9f1a78c06',
diff --git a/ash/login/ui/lock_debug_view.cc b/ash/login/ui/lock_debug_view.cc index 6060058..d1c644c 100644 --- a/ash/login/ui/lock_debug_view.cc +++ b/ash/login/ui/lock_debug_view.cc
@@ -186,7 +186,7 @@ const ui::Event& event) { // Enable or disable wallpaper blur. if (sender == toggle_blur_) { - LockScreen::Get()->ToggleBlur(); + LockScreen::Get()->ToggleBlurForDebug(); return; }
diff --git a/ash/login/ui/lock_screen.cc b/ash/login/ui/lock_screen.cc index 2340d1a..eb46596 100644 --- a/ash/login/ui/lock_screen.cc +++ b/ash/login/ui/lock_screen.cc
@@ -77,29 +77,27 @@ window->SetContentsView(contents); window->set_data_dispatcher(std::move(data_dispatcher)); window->Show(); - - for (aura::Window* window : Shell::GetAllRootWindows()) { - ui::Layer* layer = GetWallpaperLayerForWindow(window); - instance_->initial_blur_[layer] = layer->layer_blur(); - } - instance_->ToggleBlur(); } void LockScreen::Destroy() { CHECK_EQ(instance_, this); - for (aura::Window* window : Shell::GetAllRootWindows()) { - ui::Layer* layer = GetWallpaperLayerForWindow(window); - auto it = initial_blur_.find(layer); - if (it != initial_blur_.end()) - layer->SetLayerBlur(it->second); - } + // Restore the initial wallpaper bluriness if they were changed. + for (auto it = initial_blur_.begin(); it != initial_blur_.end(); ++it) + it->first->SetLayerBlur(it->second); window_->Close(); delete instance_; instance_ = nullptr; } -void LockScreen::ToggleBlur() { +void LockScreen::ToggleBlurForDebug() { + // Save the initial wallpaper bluriness upon the first time this is called. + if (instance_->initial_blur_.empty()) { + for (aura::Window* window : Shell::GetAllRootWindows()) { + ui::Layer* layer = GetWallpaperLayerForWindow(window); + instance_->initial_blur_[layer] = layer->layer_blur(); + } + } for (aura::Window* window : Shell::GetAllRootWindows()) { ui::Layer* layer = GetWallpaperLayerForWindow(window); if (layer->layer_blur() > 0.0f) {
diff --git a/ash/login/ui/lock_screen.h b/ash/login/ui/lock_screen.h index 9abc50b..cac4de7 100644 --- a/ash/login/ui/lock_screen.h +++ b/ash/login/ui/lock_screen.h
@@ -33,8 +33,8 @@ // Destroys an existing lock screen instance. void Destroy(); - // Enables/disables background blur. - void ToggleBlur(); + // Enables/disables background blur. Used for debugging purpose. + void ToggleBlurForDebug(); // Enable or disable PIN for the given user. void SetPinEnabledForUser(const AccountId& account_id, bool is_enabled);
diff --git a/ash/system/palette/palette_tray.cc b/ash/system/palette/palette_tray.cc index 4ad3258c..113fdff 100644 --- a/ash/system/palette/palette_tray.cc +++ b/ash/system/palette/palette_tray.cc
@@ -227,10 +227,13 @@ void PaletteTray::OnLockStateChanged(bool locked) { UpdateIconVisibility(); - // The user can eject the stylus during the lock screen transition, which will - // open the palette. Make sure to close it if that happens. - if (locked) + if (locked) { + palette_tool_manager_->DisableActiveTool(PaletteGroup::MODE); + + // The user can eject the stylus during the lock screen transition, which + // will open the palette. Make sure to close it if that happens. HidePalette(); + } } void PaletteTray::ClickedOutsideBubble() { @@ -391,10 +394,12 @@ if (Shell::GetAshConfig() == Config::MASH || !local_state_pref_service_) return; - // If a device has an internal stylus, mark the has seen stylus flag as true - // since we know the user has a stylus. - if (palette_utils::HasInternalStylus()) + // If a device has an internal stylus or the flag to force stylus is set, mark + // the has seen stylus flag as true since we know the user has a stylus. + if (palette_utils::HasInternalStylus() || + palette_utils::HasForcedStylusInput()) { local_state_pref_service_->SetBoolean(prefs::kHasSeenStylus, true); + } pref_change_registrar_ = base::MakeUnique<PrefChangeRegistrar>(); pref_change_registrar_->Init(local_state_pref_service_);
diff --git a/ash/system/palette/palette_tray_unittest.cc b/ash/system/palette/palette_tray_unittest.cc index e3eb808..5cf52292 100644 --- a/ash/system/palette/palette_tray_unittest.cc +++ b/ash/system/palette/palette_tray_unittest.cc
@@ -7,8 +7,10 @@ #include "ash/ash_switches.h" #include "ash/public/cpp/ash_pref_names.h" #include "ash/public/cpp/config.h" +#include "ash/session/test_session_controller_client.h" #include "ash/shell.h" #include "ash/shell_test_api.h" +#include "ash/system/palette/palette_utils.h" #include "ash/system/palette/test_palette_delegate.h" #include "ash/system/status_area_widget.h" #include "ash/system/status_area_widget_test_helper.h" @@ -18,7 +20,11 @@ #include "base/command_line.h" #include "base/memory/ptr_util.h" #include "components/prefs/testing_pref_service.h" +#include "components/session_manager/session_manager_types.h" +#include "ui/events/devices/device_data_manager.h" +#include "ui/events/devices/touchscreen_device.h" #include "ui/events/event.h" +#include "ui/events/test/device_data_manager_test_api.h" #include "ui/events/test/event_generator.h" namespace ash { @@ -30,12 +36,12 @@ void SetUp() override { base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshForceEnableStylusTools); - base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kAshEnablePaletteOnAllDisplays); AshTestBase::SetUp(); + palette_utils::SetHasStylusInputForTesting(); + Shell::RegisterLocalStatePrefs(pref_service_.registry()); ash_test_helper()->test_shell_delegate()->set_local_state_pref_service( &pref_service_); @@ -88,7 +94,7 @@ // Verify that if the has seen stylus pref is not set initially, the palette // tray's touch event watcher should be active. TEST_F(PaletteTrayTest, PaletteTrayStylusWatcherAlive) { - // TODO(crbug.com/751191): Remove the check for Mash. + // TODO(crbug.com/752997): Remove the check for Mash. if (Shell::GetAshConfig() == Config::MASH) return; @@ -100,7 +106,7 @@ // Verify if the has seen stylus pref is not set initially, the palette tray // should become visible after seeing a stylus event. TEST_F(PaletteTrayTest, PaletteTrayVisibleAfterStylusSeen) { - // TODO(crbug.com/751191): Remove the check for Mash. + // TODO(crbug.com/752997): Remove the check for Mash. if (Shell::GetAshConfig() == Config::MASH) return; @@ -123,7 +129,7 @@ // Verify if the has seen stylus pref is initially set, the palette tray is // visible. TEST_F(PaletteTrayTest, StylusSeenPrefInitiallySet) { - // TODO(crbug.com/751191): Remove the check for Mash. + // TODO(crbug.com/752997): Remove the check for Mash. if (Shell::GetAshConfig() == Config::MASH) return; @@ -137,7 +143,7 @@ // Verify the palette tray button exists and is visible if the device has an // internal stylus. TEST_F(PaletteTrayTest, PaletteTrayIsVisibleForInternalStylus) { - // TODO(crbug.com/751191): Remove the check for Mash. + // TODO(crbug.com/752997): Remove the check for Mash. if (Shell::GetAshConfig() == Config::MASH) return; @@ -146,6 +152,33 @@ EXPECT_TRUE(palette_tray_->visible()); } +// Verify that when entering or exiting the lock screen, the behavior of the +// palette tray button is as expected. +TEST_F(PaletteTrayTest, PaletteTrayOnLockScreenBehavior) { + // TODO(crbug.com/752997): Remove the check for Mash. + if (Shell::GetAshConfig() == Config::MASH) + return; + + InitForInternalStylus(); + ASSERT_TRUE(palette_tray_->visible()); + + PaletteToolManager* manager = test_api_->GetPaletteToolManager(); + manager->ActivateTool(PaletteToolId::LASER_POINTER); + EXPECT_TRUE(manager->IsToolActive(PaletteToolId::LASER_POINTER)); + + // Verify that when entering the lock screen, the palette tray button is + // hidden, and the tool that was active is no longer active. + GetSessionControllerClient()->RequestLockScreen(); + EXPECT_FALSE(manager->IsToolActive(PaletteToolId::LASER_POINTER)); + EXPECT_FALSE(palette_tray_->visible()); + + // Verify that when logging back in the tray is visible, but the tool that was + // active before locking the screen is still inactive. + GetSessionControllerClient()->UnlockScreen(); + EXPECT_TRUE(palette_tray_->visible()); + EXPECT_FALSE(manager->IsToolActive(PaletteToolId::LASER_POINTER)); +} + // Verify taps on the palette tray button results in expected behaviour. TEST_F(PaletteTrayTest, PaletteTrayWorkflow) { // Verify the palette tray button is not active, and the palette tray bubble
diff --git a/ash/system/palette/palette_utils.cc b/ash/system/palette/palette_utils.cc index c7347e8..dff37640 100644 --- a/ash/system/palette/palette_utils.cc +++ b/ash/system/palette/palette_utils.cc
@@ -19,13 +19,25 @@ namespace ash { namespace palette_utils { +namespace { +// If true the device performs as if it is hardware reports that it is stylus +// capable. +bool g_has_stylus_input_for_testing = false; +} // namespace + +bool HasForcedStylusInput() { + return base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAshForceEnableStylusTools); +} + bool HasStylusInput() { + if (g_has_stylus_input_for_testing) + return true; + // Allow the user to force enable or disable by passing a switch. If both are // present, enabling takes precedence over disabling. - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshForceEnableStylusTools)) { + if (HasForcedStylusInput()) return true; - } // Check to see if the hardware reports it is stylus capable. for (const ui::TouchscreenDevice& device : @@ -68,5 +80,9 @@ switches::kHasInternalStylus); } +void SetHasStylusInputForTesting() { + g_has_stylus_input_for_testing = true; +} + } // namespace palette_utils } // namespace ash
diff --git a/ash/system/palette/palette_utils.h b/ash/system/palette/palette_utils.h index 6451a869..ef28bbc 100644 --- a/ash/system/palette/palette_utils.h +++ b/ash/system/palette/palette_utils.h
@@ -14,6 +14,9 @@ namespace ash { namespace palette_utils { +// Returns true if the flag to force stylus input is set to true. +ASH_EXPORT bool HasForcedStylusInput(); + // Returns true if there is a stylus input device on the internal display. This // will return false even if there is a stylus input device until hardware // probing is complete (see ui::InputDeviceEventObserver). @@ -34,6 +37,9 @@ // Returns true if the device has an internal stylus. ASH_EXPORT bool HasInternalStylus(); +// Forcibly say the device is has stylus input for testing purposes. +ASH_EXPORT void SetHasStylusInputForTesting(); + } // namespace palette_utils } // namespace ash
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc index b79db51e..165416e 100644 --- a/ash/wallpaper/wallpaper_controller.cc +++ b/ash/wallpaper/wallpaper_controller.cc
@@ -302,6 +302,12 @@ session_manager::SessionState state) { CalculateWallpaperColors(); + // The wallpaper may be dimmed/blurred based on session state. The color of + // the dimming overlay depends on the prominent color cached from a previous + // calculation, or a default color if cache is not available. It should never + // depend on any in-flight color calculation. + InstallDesktopControllerForAllWindows(); + if (state == session_manager::SessionState::ACTIVE) MoveToUnlockedContainer(); else
diff --git a/ash/wallpaper/wallpaper_view.cc b/ash/wallpaper/wallpaper_view.cc index 17f34a1..ec74bc7 100644 --- a/ash/wallpaper/wallpaper_view.cc +++ b/ash/wallpaper/wallpaper_view.cc
@@ -4,6 +4,7 @@ #include "ash/wallpaper/wallpaper_view.h" +#include "ash/login/ui/login_constants.h" #include "ash/root_window_controller.h" #include "ash/session/session_controller.h" #include "ash/shell.h" @@ -18,6 +19,8 @@ #include "ui/display/manager/managed_display_info.h" #include "ui/display/screen.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/color_analysis.h" +#include "ui/gfx/color_utils.h" #include "ui/gfx/geometry/safe_integer_conversions.h" #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/transform.h" @@ -71,6 +74,23 @@ DISALLOW_COPY_AND_ASSIGN(LayerControlView); }; +// Returns the color used to darken the wallpaper, needed by login, lock, OOBE +// and add user screens. +SkColor GetWallpaperDarkenColor() { + SkColor darken_color = + Shell::Get()->wallpaper_controller()->GetProminentColor( + color_utils::ColorProfile(color_utils::LumaRange::DARK, + color_utils::SaturationRange::MUTED)); + if (darken_color == WallpaperController::kInvalidColor) + darken_color = login_constants::kDefaultBaseColor; + + darken_color = color_utils::GetResultingPaintColor( + SkColorSetA(login_constants::kDefaultBaseColor, + login_constants::kTranslucentColorDarkenAlpha), + SkColorSetA(darken_color, 0xFF)); + return SkColorSetA(darken_color, login_constants::kTranslucentAlpha); +} + } // namespace // This event handler receives events in the pre-target phase and takes care of @@ -139,6 +159,12 @@ if (wallpaper.isNull()) return; + cc::PaintFlags flags; + if (Shell::Get()->session_controller()->IsUserSessionBlocked()) { + flags.setColorFilter(SkColorFilter::MakeModeFilter( + GetWallpaperDarkenColor(), SkBlendMode::kDarken)); + } + if (layout == wallpaper::WALLPAPER_LAYOUT_CENTER_CROPPED) { // The dimension with the smallest ratio must be cropped, the other one // is preserved. Both are set in gfx::Size cropped_size. @@ -164,13 +190,14 @@ canvas->DrawImageInt( wallpaper, wallpaper_cropped_rect.x(), wallpaper_cropped_rect.y(), wallpaper_cropped_rect.width(), wallpaper_cropped_rect.height(), 0, 0, - width(), height(), true); + width(), height(), true, flags); } else if (layout == wallpaper::WALLPAPER_LAYOUT_TILE) { - canvas->TileImageInt(wallpaper, 0, 0, width(), height()); + canvas->TileImageInt(wallpaper, 0, 0, 0, 0, width(), height(), 1.0f, + &flags); } else if (layout == wallpaper::WALLPAPER_LAYOUT_STRETCH) { // This is generally not recommended as it may show artifacts. canvas->DrawImageInt(wallpaper, 0, 0, wallpaper.width(), wallpaper.height(), - 0, 0, width(), height(), true); + 0, 0, width(), height(), true, flags); } else { float image_scale = canvas->image_scale(); gfx::Rect wallpaper_rect(0, 0, wallpaper.width() / image_scale, @@ -179,7 +206,8 @@ canvas->DrawImageInt(wallpaper, 0, 0, wallpaper.width(), wallpaper.height(), (width() - wallpaper_rect.width()) / 2, (height() - wallpaper_rect.height()) / 2, - wallpaper_rect.width(), wallpaper_rect.height(), true); + wallpaper_rect.width(), wallpaper_rect.height(), true, + flags); } } @@ -235,6 +263,9 @@ aura::Window* container = root_window->GetChildById(container_id); wallpaper_widget->SetBounds(container->bounds()); + if (Shell::Get()->session_controller()->IsUserSessionBlocked()) + wallpaper_widget->GetLayer()->SetLayerBlur(login_constants::kBlurSigma); + return wallpaper_widget; }
diff --git a/base/callback_helpers.cc b/base/callback_helpers.cc index 838e6c8d..1f87a6c 100644 --- a/base/callback_helpers.cc +++ b/base/callback_helpers.cc
@@ -4,18 +4,16 @@ #include "base/callback_helpers.h" -#include "base/callback.h" - namespace base { ScopedClosureRunner::ScopedClosureRunner() {} -ScopedClosureRunner::ScopedClosureRunner(const Closure& closure) - : closure_(closure) {} +ScopedClosureRunner::ScopedClosureRunner(OnceClosure closure) + : closure_(std::move(closure)) {} ScopedClosureRunner::~ScopedClosureRunner() { if (!closure_.is_null()) - closure_.Run(); + std::move(closure_).Run(); } ScopedClosureRunner::ScopedClosureRunner(ScopedClosureRunner&& other) @@ -28,19 +26,15 @@ } void ScopedClosureRunner::RunAndReset() { - Closure old_closure = Release(); - if (!old_closure.is_null()) - old_closure.Run(); + std::move(closure_).Run(); } -void ScopedClosureRunner::ReplaceClosure(const Closure& closure) { - closure_ = closure; +void ScopedClosureRunner::ReplaceClosure(OnceClosure closure) { + closure_ = std::move(closure); } -Closure ScopedClosureRunner::Release() { - Closure result = closure_; - closure_.Reset(); - return result; +OnceClosure ScopedClosureRunner::Release() { + return std::move(closure_); } } // namespace base
diff --git a/base/callback_helpers.h b/base/callback_helpers.h index 8d622f8..6408ef4 100644 --- a/base/callback_helpers.h +++ b/base/callback_helpers.h
@@ -77,7 +77,7 @@ class BASE_EXPORT ScopedClosureRunner { public: ScopedClosureRunner(); - explicit ScopedClosureRunner(const Closure& closure); + explicit ScopedClosureRunner(OnceClosure closure); ~ScopedClosureRunner(); ScopedClosureRunner(ScopedClosureRunner&& other); @@ -90,13 +90,13 @@ void RunAndReset(); // Replaces closure with the new one releasing the old one without calling it. - void ReplaceClosure(const Closure& closure); + void ReplaceClosure(OnceClosure closure); // Releases the Closure without calling. - Closure Release() WARN_UNUSED_RESULT; + OnceClosure Release() WARN_UNUSED_RESULT; private: - Closure closure_; + OnceClosure closure_; DISALLOW_COPY_AND_ASSIGN(ScopedClosureRunner); };
diff --git a/base/callback_helpers_unittest.cc b/base/callback_helpers_unittest.cc index 9166d8a..1c1102d 100644 --- a/base/callback_helpers_unittest.cc +++ b/base/callback_helpers_unittest.cc
@@ -43,14 +43,14 @@ TEST(CallbackHelpersTest, TestScopedClosureRunnerRelease) { int run_count = 0; - base::Closure c; + base::OnceClosure c; { base::ScopedClosureRunner runner(base::Bind(&Increment, &run_count)); c = runner.Release(); EXPECT_EQ(0, run_count); } EXPECT_EQ(0, run_count); - c.Run(); + std::move(c).Run(); EXPECT_EQ(1, run_count); }
diff --git a/base/mac/bind_objc_block_unittest.mm b/base/mac/bind_objc_block_unittest.mm index 1b1a50c..2b18672 100644 --- a/base/mac/bind_objc_block_unittest.mm +++ b/base/mac/bind_objc_block_unittest.mm
@@ -35,7 +35,7 @@ TEST(BindObjcBlockTest, TestScopedClosureRunnerRelease) { int run_count = 0; int* ptr = &run_count; - base::Closure c; + base::OnceClosure c; { base::ScopedClosureRunner runner(base::BindBlock(^{ (*ptr)++; @@ -44,7 +44,7 @@ EXPECT_EQ(0, run_count); } EXPECT_EQ(0, run_count); - c.Run(); + std::move(c).Run(); EXPECT_EQ(1, run_count); }
diff --git a/base/mac/bind_objc_block_unittest_arc.mm b/base/mac/bind_objc_block_unittest_arc.mm index c4c268e7..24ec9748 100644 --- a/base/mac/bind_objc_block_unittest_arc.mm +++ b/base/mac/bind_objc_block_unittest_arc.mm
@@ -34,7 +34,7 @@ TEST(BindObjcBlockTestARC, TestScopedClosureRunnerRelease) { int run_count = 0; int* ptr = &run_count; - base::Closure c; + base::OnceClosure c; { base::ScopedClosureRunner runner(base::BindBlockArc(^{ (*ptr)++; @@ -43,7 +43,7 @@ EXPECT_EQ(0, run_count); } EXPECT_EQ(0, run_count); - c.Run(); + std::move(c).Run(); EXPECT_EQ(1, run_count); }
diff --git a/base/memory/weak_ptr.cc b/base/memory/weak_ptr.cc index 81f02ea6..8879651 100644 --- a/base/memory/weak_ptr.cc +++ b/base/memory/weak_ptr.cc
@@ -4,69 +4,50 @@ #include "base/memory/weak_ptr.h" -#include "base/debug/leak_annotations.h" - namespace base { namespace internal { -constexpr uintptr_t kTrueMask = ~static_cast<uintptr_t>(0); - -WeakReference::Flag::Flag() : is_valid_(kTrueMask) { +WeakReference::Flag::Flag() : is_valid_(true) { // Flags only become bound when checked for validity, or invalidated, // so that we can check that later validity/invalidation operations on // the same Flag take place on the same sequenced thread. - DETACH_FROM_SEQUENCE(sequence_checker_); -} - -WeakReference::Flag::Flag(WeakReference::Flag::NullFlagTag) : is_valid_(false) { - // There is no need for DETACH_FROM_SEQUENCE(sequence_checker_) because the - // null flag doesn't participate in the sequence checks. See DCHECK in - // Invalidate() and IsValid(). - - // Keep the object alive perpetually, even when there are no references to it. - AddRef(); -} - -WeakReference::Flag* WeakReference::Flag::NullFlag() { - ANNOTATE_SCOPED_MEMORY_LEAK; - static Flag* g_null_flag = new Flag(kNullFlagTag); - return g_null_flag; + sequence_checker_.DetachFromSequence(); } void WeakReference::Flag::Invalidate() { -#if DCHECK_IS_ON() - if (this == NullFlag()) { - // The Null Flag does not participate in the sequence checks below. - // Since its state never changes, it can be accessed from any thread. - DCHECK(!is_valid_); - return; - } // The flag being invalidated with a single ref implies that there are no - // weak pointers in existence. Allow deletion on other thread in this - // case. + // weak pointers in existence. Allow deletion on other thread in this case. DCHECK(sequence_checker_.CalledOnValidSequence() || HasOneRef()) << "WeakPtrs must be invalidated on the same sequenced thread."; -#endif - is_valid_ = 0; + is_valid_ = false; } -WeakReference::Flag::~Flag() {} - -WeakReference::WeakReference() : flag_(Flag::NullFlag()) {} - -WeakReference::~WeakReference() {} - -WeakReference::WeakReference(const Flag* flag) : flag_(flag) {} - -WeakReference::WeakReference(WeakReference&& other) - : flag_(std::move(other.flag_)) { - other.flag_ = Flag::NullFlag(); +bool WeakReference::Flag::IsValid() const { + DCHECK(sequence_checker_.CalledOnValidSequence()) + << "WeakPtrs must be checked on the same sequenced thread."; + return is_valid_; } +WeakReference::Flag::~Flag() { +} + +WeakReference::WeakReference() { +} + +WeakReference::WeakReference(const Flag* flag) : flag_(flag) { +} + +WeakReference::~WeakReference() { +} + +WeakReference::WeakReference(WeakReference&& other) = default; + WeakReference::WeakReference(const WeakReference& other) = default; -WeakReferenceOwner::WeakReferenceOwner() - : flag_(WeakReference::Flag::NullFlag()) {} +bool WeakReference::is_valid() const { return flag_.get() && flag_->IsValid(); } + +WeakReferenceOwner::WeakReferenceOwner() { +} WeakReferenceOwner::~WeakReferenceOwner() { Invalidate(); @@ -81,9 +62,9 @@ } void WeakReferenceOwner::Invalidate() { - if (flag_ != WeakReference::Flag::NullFlag()) { + if (flag_.get()) { flag_->Invalidate(); - flag_ = WeakReference::Flag::NullFlag(); + flag_ = NULL; } }
diff --git a/base/memory/weak_ptr.h b/base/memory/weak_ptr.h index d84e37e..5c9ed54 100644 --- a/base/memory/weak_ptr.h +++ b/base/memory/weak_ptr.h
@@ -96,39 +96,16 @@ public: Flag(); - // Get a pointer to the "Null Flag", a sentinel object used by WeakReference - // objects that don't point to a valid Flag, either because they're default - // constructed or because they have been invalidated. This can be used like - // any other Flag object, but it is invalidated already from the start, and - // its refcount will never reach zero. - static Flag* NullFlag(); - void Invalidate(); - - // Returns a pointer-sized bitmask of all 1s if valid or all 0s otherwise. - uintptr_t IsValid() const { -#if DCHECK_IS_ON() - if (this == NullFlag()) { - // The Null Flag does not participate in the sequence checks below. - // Since its state never changes, it can be accessed from any thread. - DCHECK(!is_valid_); - return 0; - } - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -#endif - return is_valid_; - } + bool IsValid() const; private: friend class base::RefCountedThreadSafe<Flag>; - enum NullFlagTag { kNullFlagTag }; - Flag(NullFlagTag); - ~Flag(); - uintptr_t is_valid_; - SEQUENCE_CHECKER(sequence_checker_); + SequenceChecker sequence_checker_; + bool is_valid_; }; WeakReference(); @@ -140,11 +117,9 @@ WeakReference& operator=(WeakReference&& other) = default; WeakReference& operator=(const WeakReference& other) = default; - uintptr_t is_valid() const { return flag_->IsValid(); } + bool is_valid() const; private: - // Note: To avoid null-checks, flag_ always points to either Flag::NullFlag() - // or some other object. scoped_refptr<const Flag> flag_; }; @@ -156,7 +131,7 @@ WeakReference GetRef() const; bool HasRefs() const { - return flag_ != WeakReference::Flag::NullFlag() && !flag_->HasOneRef(); + return flag_.get() && !flag_->HasOneRef(); } void Invalidate(); @@ -261,10 +236,7 @@ } T* get() const { - // Intentionally bitwise and; see command on Flag::IsValid(). This provides - // a fast way of conditionally retrieving the pointer, and conveniently sets - // EFLAGS for any null-check performed by the caller. - return reinterpret_cast<T*>(ref_.is_valid() & ptr_); + return ref_.is_valid() ? reinterpret_cast<T*>(ptr_) : nullptr; } T& operator*() const {
diff --git a/build/android/pylib/local/local_test_server_spawner.py b/build/android/pylib/local/local_test_server_spawner.py index db9fbfd..16a7eb1 100644 --- a/build/android/pylib/local/local_test_server_spawner.py +++ b/build/android/pylib/local/local_test_server_spawner.py
@@ -2,9 +2,53 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import time + from devil.android import forwarder -from pylib import chrome_test_server_spawner +from devil.android import ports from pylib.base import test_server +from pylib.constants import host_paths + +with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): + import chrome_test_server_spawner + +def _WaitUntil(predicate, max_attempts=5): + """Blocks until the provided predicate (function) is true. + + Returns: + Whether the provided predicate was satisfied once (before the timeout). + """ + sleep_time_sec = 0.025 + for _ in xrange(1, max_attempts): + if predicate(): + return True + time.sleep(sleep_time_sec) + sleep_time_sec = min(1, sleep_time_sec * 2) # Don't wait more than 1 sec. + return False + + +class PortForwarderAndroid(chrome_test_server_spawner.PortForwarder): + def __init__(self, device, tool): + self.device = device + self.tool = tool + + def Map(self, port_pairs): + forwarder.Forwarder.Map(port_pairs, self.device, self.tool) + + def GetDevicePortForHostPort(self, host_port): + return forwarder.Forwarder.DevicePortForHostPort(host_port) + + def WaitHostPortAvailable(self, port): + return _WaitUntil(lambda: ports.IsHostPortAvailable(port)) + + def WaitPortNotAvailable(self, port): + return _WaitUntil(lambda: not ports.IsHostPortAvailable(port)) + + def WaitDevicePortReady(self, port): + return _WaitUntil(lambda: ports.IsDevicePortUsed(self.device, port)) + + def Unmap(self, device_port): + forwarder.Forwarder.UnmapDevicePort(device_port, self.device) class LocalTestServerSpawner(test_server.TestServer): @@ -13,7 +57,7 @@ super(LocalTestServerSpawner, self).__init__() self._device = device self._spawning_server = chrome_test_server_spawner.SpawningServer( - port, device, tool) + port, PortForwarderAndroid(device, tool)) self._tool = tool @property
diff --git a/build/android/test_runner.pydeps b/build/android/test_runner.pydeps index e3e22cf..4084940 100644 --- a/build/android/test_runner.pydeps +++ b/build/android/test_runner.pydeps
@@ -113,6 +113,7 @@ ../../tools/swarming_client/libs/logdog/stream.py ../../tools/swarming_client/libs/logdog/streamname.py ../../tools/swarming_client/libs/logdog/varint.py +../util/lib/common/chrome_test_server_spawner.py ../util/lib/common/unittest_util.py devil_chromium.py pylib/__init__.py @@ -129,7 +130,6 @@ pylib/base/test_run.py pylib/base/test_run_factory.py pylib/base/test_server.py -pylib/chrome_test_server_spawner.py pylib/constants/__init__.py pylib/constants/host_paths.py pylib/gtest/__init__.py
diff --git a/build/args/headless.gn b/build/args/headless.gn index 2f8a2633..9452c15 100644 --- a/build/args/headless.gn +++ b/build/args/headless.gn
@@ -15,9 +15,6 @@ # Embed resource.pak into binary to simplify deployment. headless_use_embedded_resources = true -# Expose headless bindings for freetype library bundled with Chromium. -headless_fontconfig_utils = true - # Remove a dependency on a system fontconfig library. use_bundled_fontconfig = true
diff --git a/build/config/ui.gni b/build/config/ui.gni index ce384b5..6ce77e6 100644 --- a/build/config/ui.gni +++ b/build/config/ui.gni
@@ -31,7 +31,7 @@ # Indicates if Aura is enabled. Aura is a low-level windowing library, sort # of a replacement for GDI or GTK. - use_aura = is_win || is_linux + use_aura = is_win || is_linux || is_fuchsia # Whether we should use glib, a low level C utility library. use_glib = is_linux @@ -39,8 +39,8 @@ declare_args() { # True means the UI is built using the "views" framework. - toolkit_views = - (is_mac || is_win || is_chromeos || use_aura) && !is_chromecast + toolkit_views = (is_mac || is_win || is_chromeos || use_aura) && + !is_chromecast && !is_fuchsia } # Additional dependent variables -----------------------------------------------
diff --git a/build/android/pylib/chrome_test_server_spawner.py b/build/util/lib/common/chrome_test_server_spawner.py similarity index 84% rename from build/android/pylib/chrome_test_server_spawner.py rename to build/util/lib/common/chrome_test_server_spawner.py index bd729c8..5ba8de7 100644 --- a/build/android/pylib/chrome_test_server_spawner.py +++ b/build/util/lib/common/chrome_test_server_spawner.py
@@ -1,4 +1,4 @@ -# Copyright 2013 The Chromium Authors. All rights reserved. +# Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -21,21 +21,19 @@ import time import urlparse -from devil.android import forwarder -from devil.android import ports -from pylib import constants -from pylib.constants import host_paths +DIR_SOURCE_ROOT = os.path.abspath( + os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, + os.pardir)) # Path that are needed to import necessary modules when launching a testserver. os.environ['PYTHONPATH'] = os.environ.get('PYTHONPATH', '') + (':%s:%s:%s:%s:%s' - % (os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party'), - os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party', 'tlslite'), - os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party', 'pyftpdlib', - 'src'), - os.path.join(host_paths.DIR_SOURCE_ROOT, 'net', 'tools', 'testserver'), - os.path.join(host_paths.DIR_SOURCE_ROOT, 'components', 'sync', 'tools', + % (os.path.join(DIR_SOURCE_ROOT, 'third_party'), + os.path.join(DIR_SOURCE_ROOT, 'third_party', 'tlslite'), + os.path.join(DIR_SOURCE_ROOT, 'third_party', 'pyftpdlib', 'src'), + os.path.join(DIR_SOURCE_ROOT, 'net', 'tools', 'testserver'), + os.path.join(DIR_SOURCE_ROOT, 'components', 'sync', 'tools', 'testserver'))) @@ -51,35 +49,6 @@ # The timeout (in seconds) of starting up the Python test server. TEST_SERVER_STARTUP_TIMEOUT = 10 -def _WaitUntil(predicate, max_attempts=5): - """Blocks until the provided predicate (function) is true. - - Returns: - Whether the provided predicate was satisfied once (before the timeout). - """ - sleep_time_sec = 0.025 - for _ in xrange(1, max_attempts): - if predicate(): - return True - time.sleep(sleep_time_sec) - sleep_time_sec = min(1, sleep_time_sec * 2) # Don't wait more than 1 sec. - return False - - -def _CheckPortAvailable(port): - """Returns True if |port| is available.""" - return _WaitUntil(lambda: ports.IsHostPortAvailable(port)) - - -def _CheckPortNotAvailable(port): - """Returns True if |port| is not available.""" - return _WaitUntil(lambda: not ports.IsHostPortAvailable(port)) - - -def _CheckDevicePortStatus(device, port): - """Returns whether the provided port is used.""" - return _WaitUntil(lambda: ports.IsDevicePortUsed(device, port)) - def _GetServerTypeCommandLine(server_type): """Returns the command-line by the given server type. @@ -98,10 +67,35 @@ return SERVER_TYPES[server_type] +class PortForwarder: + def Map(self, port_pairs): + pass + + def GetDevicePortForHostPort(self, host_port): + """Returns the device port that corresponds to a given host port.""" + return host_port + + def WaitHostPortAvailable(self, port): + """Returns True if |port| is available.""" + return True + + def WaitPortNotAvailable(self, port): + """Returns True if |port| is not available.""" + return True + + def WaitDevicePortReady(self, port): + """Returns whether the provided port is used.""" + return True + + def Unmap(self, device_port): + """Unmaps specified port""" + pass + + class TestServerThread(threading.Thread): """A thread to run the test server in a separate process.""" - def __init__(self, ready_event, arguments, device, tool): + def __init__(self, ready_event, arguments, port_forwarder): """Initialize TestServerThread with the following argument. Args: @@ -112,12 +106,11 @@ """ threading.Thread.__init__(self) self.wait_event = threading.Event() - self.stop_flag = False + self.stop_event = threading.Event() self.ready_event = ready_event self.ready_event.clear() self.arguments = arguments - self.device = device - self.tool = tool + self.port_forwarder = port_forwarder self.test_server_process = None self.is_ready = False self.host_port = self.arguments['port'] @@ -166,7 +159,7 @@ port_json = json.loads(port_json) if port_json.has_key('port') and isinstance(port_json['port'], int): self.host_port = port_json['port'] - return _CheckPortNotAvailable(self.host_port) + return self.port_forwarder.WaitPortNotAvailable(self.host_port) logging.error('Failed to get port information from the server data.') return False @@ -218,7 +211,7 @@ logging.info('Start running the thread!') self.wait_event.clear() self._GenerateCommandLineArguments() - command = host_paths.DIR_SOURCE_ROOT + command = DIR_SOURCE_ROOT if self.arguments['server-type'] == 'sync': command = [os.path.join(command, 'components', 'sync', 'tools', 'testserver', @@ -236,29 +229,30 @@ # paths in the arguments are resolved correctly. self.process = subprocess.Popen( command, preexec_fn=self._CloseUnnecessaryFDsForTestServerProcess, - cwd=host_paths.DIR_SOURCE_ROOT) + cwd=DIR_SOURCE_ROOT) if unbuf: os.environ['PYTHONUNBUFFERED'] = unbuf if self.process: if self.pipe_out: self.is_ready = self._WaitToStartAndGetPortFromTestServer() else: - self.is_ready = _CheckPortNotAvailable(self.host_port) + self.is_ready = self.port_forwarder.WaitPortNotAvailable(self.host_port) if self.is_ready: - forwarder.Forwarder.Map([(0, self.host_port)], self.device, self.tool) + self.port_forwarder.Map([(0, self.host_port)]) + # Check whether the forwarder is ready on the device. self.is_ready = False - device_port = forwarder.Forwarder.DevicePortForHostPort(self.host_port) - if device_port and _CheckDevicePortStatus(self.device, device_port): + device_port = self.port_forwarder.GetDevicePortForHostPort(self.host_port) + if device_port and self.port_forwarder.WaitDevicePortReady(device_port): self.is_ready = True self.forwarder_device_port = device_port # Wake up the request handler thread. self.ready_event.set() # Keep thread running until Stop() gets called. - _WaitUntil(lambda: self.stop_flag, max_attempts=sys.maxint) + self.stop_event.wait() if self.process.poll() is None: self.process.kill() - forwarder.Forwarder.UnmapDevicePort(self.forwarder_device_port, self.device) + self.port_forwarder.Unmap(self.forwarder_device_port) self.process = None self.is_ready = False if self.pipe_out: @@ -276,7 +270,7 @@ """ if not self.process: return - self.stop_flag = True + self.stop_event.set() self.wait_event.wait() @@ -333,8 +327,7 @@ self.server.test_server_instance = TestServerThread( ready_event, json.loads(test_server_argument_json), - self.server.device, - self.server.tool) + self.server.port_forwarder) self.server.test_server_instance.setDaemon(True) self.server.test_server_instance.start() ready_event.wait() @@ -360,7 +353,7 @@ logging.info('Handling request to kill a test server on port: %d.', port) self.server.test_server_instance.Stop() # Make sure the status of test server is correct before sending response. - if _CheckPortAvailable(port): + if self.server.port_forwarder.WaitHostPortAvailable(port): self._SendResponse(200, 'OK', {}, 'killed') logging.info('Test server on port %d is killed', port) else: @@ -401,14 +394,12 @@ class SpawningServer(object): """The class used to start/stop a http server.""" - def __init__(self, test_server_spawner_port, device, tool): + def __init__(self, test_server_spawner_port, port_forwarder): logging.info('Creating new spawner on port: %d.', test_server_spawner_port) self.server = BaseHTTPServer.HTTPServer(('', test_server_spawner_port), SpawningServerRequestHandler) - self.server.device = device - self.server.tool = tool + self.server.port_forwarder = port_forwarder self.server.test_server_instance = None - self.server.build_type = constants.GetBuildType() def _Listen(self): logging.info('Starting test server spawner')
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index 627df9c..e12ef59 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc
@@ -380,8 +380,18 @@ bmf_start_to_activate + compositor_timing_history_->BeginMainFrameQueueDurationCriticalEstimate(); + // TODO(khushalsagar): We need to consider the deadline fudge factor here to + // match the deadline used in BEGIN_IMPL_FRAME_DEADLINE_MODE_REGULAR mode + // (used in the case where the impl thread needs to redraw). In the case where + // main_frame_to_active is fast, we should consider using + // BEGIN_IMPL_FRAME_DEADLINE_MODE_LATE instead to avoid putting the main + // thread in high latency mode. See crbug.com/753146. + base::TimeDelta bmf_to_activate_threshold = + adjusted_args.interval - + compositor_timing_history_->DrawDurationEstimate() - kDeadlineFudgeFactor; + state_machine_.SetCriticalBeginMainFrameToActivateIsFast( - bmf_to_activate_estimate_critical < adjusted_args.interval); + bmf_to_activate_estimate_critical < bmf_to_activate_threshold); // Update the BeginMainFrame args now that we know whether the main // thread will be on the critical path or not.
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc index 6a929358..1744eb2c 100644 --- a/cc/scheduler/scheduler_unittest.cc +++ b/cc/scheduler/scheduler_unittest.cc
@@ -3568,5 +3568,59 @@ client_->Reset(); } +TEST_F(SchedulerTest, CriticalBeginMainFrameToActivateIsFast) { + SetUpScheduler(EXTERNAL_BFS); + + scheduler_->SetNeedsRedraw(); + base::TimeDelta estimate_duration = base::TimeDelta::FromMilliseconds(1); + fake_compositor_timing_history_->SetAllEstimatesTo(estimate_duration); + + // If we have a scroll handler but the critical main frame is slow, we should + // still prioritize impl thread latency. + scheduler_->SetTreePrioritiesAndScrollState( + SMOOTHNESS_TAKES_PRIORITY, + ScrollHandlerState::SCROLL_AFFECTS_SCROLL_HANDLER); + scheduler_->SetNeedsRedraw(); + // An interval of 2ms makes sure that the main frame is considered slow. + base::TimeDelta interval = base::TimeDelta::FromMilliseconds(2); + now_src_->Advance(interval); + viz::BeginFrameArgs args = viz::BeginFrameArgs::Create( + BEGINFRAME_FROM_HERE, 0u, 1u, now_src_->NowTicks(), + now_src_->NowTicks() + interval, interval, viz::BeginFrameArgs::NORMAL); + fake_external_begin_frame_source_->TestOnBeginFrame(args); + EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority()); + + task_runner().RunPendingTasks(); // Run posted deadline to finish the frame. + ASSERT_FALSE(client_->IsInsideBeginImplFrame()); + + // Set an interval of 10ms. The bmf_to_activate_interval should be 1*4 = 4ms, + // to account for queue + main_frame + pending_tree + activation durations. + // With a draw time of 1ms and fudge factor of 1ms, the interval available for + // the main frame to be activated is 8ms, so it should be considered fast. + scheduler_->SetNeedsRedraw(); + interval = base::TimeDelta::FromMilliseconds(10); + now_src_->Advance(interval); + args = viz::BeginFrameArgs::Create( + BEGINFRAME_FROM_HERE, 0u, 2u, now_src_->NowTicks(), + now_src_->NowTicks() + interval, interval, viz::BeginFrameArgs::NORMAL); + fake_external_begin_frame_source_->TestOnBeginFrame(args); + EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority()); + + task_runner().RunPendingTasks(); // Run posted deadline to finish the frame. + ASSERT_FALSE(client_->IsInsideBeginImplFrame()); + + // Increase the draw duration to decrease the time available for the main + // frame. This should prioritize the impl thread. + scheduler_->SetNeedsRedraw(); + fake_compositor_timing_history_->SetDrawDurationEstimate( + base::TimeDelta::FromMilliseconds(7)); + now_src_->Advance(interval); + args = viz::BeginFrameArgs::Create( + BEGINFRAME_FROM_HERE, 0u, 3u, now_src_->NowTicks(), + now_src_->NowTicks() + interval, interval, viz::BeginFrameArgs::NORMAL); + fake_external_begin_frame_source_->TestOnBeginFrame(args); + EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority()); +} + } // namespace } // namespace cc
diff --git a/cc/test/scheduler_test_common.h b/cc/test/scheduler_test_common.h index 493be9b..f4f8260c 100644 --- a/cc/test/scheduler_test_common.h +++ b/cc/test/scheduler_test_common.h
@@ -118,6 +118,10 @@ state_machine_.SetCriticalBeginMainFrameToActivateIsFast(is_fast); } + bool ImplLatencyTakesPriority() const { + return state_machine_.ImplLatencyTakesPriority(); + } + protected: // Overridden from Scheduler. base::TimeTicks Now() const override;
diff --git a/chrome/VERSION b/chrome/VERSION index bb54dfd5..1073fdb 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=62 MINOR=0 -BUILD=3179 +BUILD=3180 PATCH=0
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionNavigationTest.java index b3eb1e9..2c6fbdb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/PermissionNavigationTest.java
@@ -4,11 +4,9 @@ package org.chromium.chrome.browser.permissions; -import android.support.test.filters.MediumTest; - import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; @@ -29,9 +27,11 @@ * * @throws Exception */ - @MediumTest - @Feature({"Permissions"}) + // @MediumTest + // @Feature({"Permissions"}) @CommandLineFlags.Add({NO_GESTURE_FEATURE, FORCE_FIELDTRIAL, FORCE_FIELDTRIAL_PARAMS}) + // Flaky on official bots, https://crbug.com/699851#c8 + @DisabledTest public void testNavigationDismissesModalPermissionPrompt() throws Exception { setUpUrl(TEST_FILE); runJavaScriptCodeInCurrentTab("requestGeolocationPermission()");
diff --git a/chrome/browser/android/feedback/screenshot_task.cc b/chrome/browser/android/feedback/screenshot_task.cc index a96e3e7..7a69153 100644 --- a/chrome/browser/android/feedback/screenshot_task.cc +++ b/chrome/browser/android/feedback/screenshot_task.cc
@@ -7,7 +7,6 @@ #include "base/android/scoped_java_ref.h" #include "base/bind.h" #include "base/memory/ref_counted_memory.h" -#include "base/threading/thread_task_runner_handle.h" #include "jni/ScreenshotTask_jni.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/android/window_android.h" @@ -47,7 +46,7 @@ native_window_android); gfx::Rect window_bounds(window_width, window_height); ui::GrabWindowSnapshotAsyncPNG( - window_android, window_bounds, base::ThreadTaskRunnerHandle::Get(), + window_android, window_bounds, base::Bind(&SnapshotCallback, env, ScopedJavaGlobalRef<jobject>(env, jcallback))); }
diff --git a/chrome/browser/android/locale/special_locale_handler.cc b/chrome/browser/android/locale/special_locale_handler.cc index a4345c2..d0fd86f 100644 --- a/chrome/browser/android/locale/special_locale_handler.cc +++ b/chrome/browser/android/locale/special_locale_handler.cc
@@ -10,6 +10,7 @@ #include "base/memory/ptr_util.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/search_engines/template_url_service_factory.h" +#include "chrome/browser/search_engines/ui_thread_search_terms_data.h" #include "components/search_engines/prepopulated_engines.h" #include "components/search_engines/template_url_data.h" #include "components/search_engines/template_url_prepopulate_data.h" @@ -74,8 +75,9 @@ // Otherwise, matching based on keyword is sufficient and preferred as // some logically distinct search engines share the same prepopulate ID and // only differ on keyword. - bool exists = template_url_service_->GetTemplateURLForKeyword( - data_url->keyword()) != nullptr; + const TemplateURL* existing_url = + template_url_service_->GetTemplateURLForKeyword(data_url->keyword()); + bool exists = existing_url != nullptr; if (!exists && data_url->prepopulate_id == TemplateURLPrepopulateData::google.id) { auto existing_urls = template_url_service_->GetTemplateURLs(); @@ -88,8 +90,23 @@ } } } - if (exists) + + if (exists) { + // Update the visit time of any existing custom search engines to ensure + // they are not filtered out in TemplateUrlServicAndroid::LoadTemplateURLs + if (!template_url_service_->IsPrepopulatedOrCreatedByPolicy( + existing_url)) { + UIThreadSearchTermsData search_terms_data(profile_); + + TemplateURLService::URLVisitedDetails visited_details; + visited_details.url = + existing_url->GenerateSearchURL(search_terms_data); + visited_details.is_keyword_transition = false; + template_url_service_->OnHistoryURLVisited(visited_details); + } + continue; + } data_url.get()->safe_for_autoreplace = true; std::unique_ptr<TemplateURL> turl(
diff --git a/chrome/browser/apps/app_url_redirector.cc b/chrome/browser/apps/app_url_redirector.cc index 58b91cf0..4b10b98d 100644 --- a/chrome/browser/apps/app_url_redirector.cc +++ b/chrome/browser/apps/app_url_redirector.cc
@@ -34,6 +34,25 @@ namespace { +bool ShouldOverrideNavigation( + const Extension* app, + content::WebContents* source, + const navigation_interception::NavigationParams& params) { + Browser* browser = chrome::FindBrowserWithWebContents(source); + if (browser == nullptr) { + DVLOG(1) << "Don't override: No browser, can't know if already in app."; + return false; + } + + if (browser->app_name() == + web_app::GenerateApplicationNameFromExtensionId(app->id())) { + DVLOG(1) << "Don't override: Already in app."; + return false; + } + + return true; +} + bool LaunchAppWithUrl( const scoped_refptr<const Extension> app, const std::string& handler_id, @@ -70,17 +89,8 @@ Profile::FromBrowserContext(source->GetBrowserContext()); if (app->from_bookmark()) { - Browser* browser = chrome::FindBrowserWithWebContents(source); - if (browser == nullptr) { - DVLOG(1) << "Don't override: No browser, can't know if already in app."; + if (!ShouldOverrideNavigation(app.get(), source, params)) return false; - } - - if (browser->app_name() == - web_app::GenerateApplicationNameFromExtensionId(app->id())) { - DVLOG(1) << "Don't override: Already in app."; - return false; - } AppLaunchParams launch_params( profile, app.get(), extensions::LAUNCH_CONTAINER_WINDOW,
diff --git a/chrome/browser/chromeos/accessibility/accessibility_highlight_manager_interactive_uitest.cc b/chrome/browser/chromeos/accessibility/accessibility_highlight_manager_interactive_uitest.cc index eff5d5f1..26e9f7e 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_highlight_manager_interactive_uitest.cc +++ b/chrome/browser/chromeos/accessibility/accessibility_highlight_manager_interactive_uitest.cc
@@ -8,7 +8,6 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/run_loop.h" -#include "base/threading/sequenced_worker_pool.h" #include "chrome/browser/chromeos/ui/accessibility_focus_ring_controller.h" #include "chrome/test/base/in_process_browser_test.h" #include "chromeos/chromeos_switches.h" @@ -136,7 +135,6 @@ aura::Window* window = ash::Shell::GetPrimaryRootWindow(); ui::GrabWindowSnapshotAndScaleAsync( window, bounds, bounds.size(), - content::BrowserThread::GetBlockingPool(), base::Bind(&AccessibilityHighlightManagerTest::GotSnapshot, base::Unretained(this))); base::RunLoop run_loop;
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc index 5762c0d..522ec8da 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc +++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc
@@ -257,8 +257,6 @@ } ui::GrabWindowSnapshotAsyncJPEG( window, gfx::Rect(window->bounds().size()), - base::CreateTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::USER_BLOCKING}), base::Bind(&ScreenshotCallback, callback)); }
diff --git a/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.cc b/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.cc index b6fcb74c..0f59f64 100644 --- a/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.cc +++ b/chrome/browser/chromeos/login/screenshot_testing/screenshot_tester.cc
@@ -11,7 +11,6 @@ #include "base/command_line.h" #include "base/files/file_util.h" #include "base/run_loop.h" -#include "base/task_scheduler/post_task.h" #include "chrome/browser/chromeos/login/screenshot_testing/SkDiffPixelsMetric.h" #include "chrome/browser/chromeos/login/screenshot_testing/SkImageDiffer.h" #include "chrome/browser/chromeos/login/screenshot_testing/SkPMetric.h" @@ -216,9 +215,6 @@ base::RunLoop run_loop; ui::GrabWindowSnapshotAsyncPNG( primary_window, rect, - base::CreateTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}), base::Bind(&ScreenshotTester::ReturnScreenshot, weak_factory_.GetWeakPtr(), base::Unretained(&run_loop), &screenshot));
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_commands_factory_chromeos.cc b/chrome/browser/chromeos/policy/remote_commands/device_commands_factory_chromeos.cc index f98e67b..0991491 100644 --- a/chrome/browser/chromeos/policy/remote_commands/device_commands_factory_chromeos.cc +++ b/chrome/browser/chromeos/policy/remote_commands/device_commands_factory_chromeos.cc
@@ -34,11 +34,8 @@ return base::WrapUnique<RemoteCommandJob>(new DeviceCommandRebootJob( chromeos::DBusThreadManager::Get()->GetPowerManagerClient())); case em::RemoteCommand_Type_DEVICE_SCREENSHOT: - return base::WrapUnique<RemoteCommandJob>( - new DeviceCommandScreenshotJob(base::MakeUnique<ScreenshotDelegate>( - base::CreateSequencedTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::BACKGROUND, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})))); + return base::WrapUnique<RemoteCommandJob>(new DeviceCommandScreenshotJob( + base::MakeUnique<ScreenshotDelegate>())); case em::RemoteCommand_Type_DEVICE_SET_VOLUME: return base::WrapUnique<RemoteCommandJob>( new DeviceCommandSetVolumeJob());
diff --git a/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.cc b/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.cc index eec0979..06e1e4e 100644 --- a/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.cc +++ b/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.h" +#include <string> + #include "base/memory/ptr_util.h" #include "base/syslog_logging.h" #include "base/threading/thread_task_runner_handle.h" @@ -18,10 +20,7 @@ namespace policy { -ScreenshotDelegate::ScreenshotDelegate( - scoped_refptr<base::TaskRunner> blocking_task_runner) - : blocking_task_runner_(blocking_task_runner), weak_ptr_factory_(this) { -} +ScreenshotDelegate::ScreenshotDelegate() : weak_ptr_factory_(this) {} ScreenshotDelegate::~ScreenshotDelegate() { } @@ -43,7 +42,7 @@ const gfx::Rect& source_rect, const ui::GrabWindowSnapshotAsyncPNGCallback& callback) { ui::GrabWindowSnapshotAsyncPNG( - window, source_rect, blocking_task_runner_, + window, source_rect, base::Bind(&ScreenshotDelegate::StoreScreenshot, weak_ptr_factory_.GetWeakPtr(), callback)); }
diff --git a/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.h b/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.h index 6dbba859..639dfee0b 100644 --- a/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.h +++ b/chrome/browser/chromeos/policy/remote_commands/screenshot_delegate.h
@@ -10,7 +10,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "base/task_runner.h" #include "chrome/browser/chromeos/policy/remote_commands/device_command_screenshot_job.h" #include "chrome/browser/chromeos/policy/upload_job.h" #include "ui/gfx/geometry/rect.h" @@ -24,8 +23,7 @@ // aura's GrabWindowSnapshotAsyncPNG() to acquire the window snapshot. class ScreenshotDelegate : public DeviceCommandScreenshotJob::Delegate { public: - explicit ScreenshotDelegate( - scoped_refptr<base::TaskRunner> blocking_task_runner); + ScreenshotDelegate(); ~ScreenshotDelegate() override; // DeviceCommandScreenshotJob::Delegate: @@ -42,8 +40,6 @@ void StoreScreenshot(const ui::GrabWindowSnapshotAsyncPNGCallback& callback, scoped_refptr<base::RefCountedMemory> png_data); - scoped_refptr<base::TaskRunner> blocking_task_runner_; - base::WeakPtrFactory<ScreenshotDelegate> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ScreenshotDelegate);
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc index 4d21cead..a96a96d 100644 --- a/chrome/browser/devtools/devtools_sanity_browsertest.cc +++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -2043,6 +2043,10 @@ RunTest("testEmulateNetworkConditions", kEmulateNetworkConditionsPage); } +IN_PROC_BROWSER_TEST_F(DevToolsNetInfoTest, OfflineNetworkConditions) { + RunTest("testOfflineNetworkConditions", kEmulateNetworkConditionsPage); +} + class StaticURLDataSource : public content::URLDataSource { public: StaticURLDataSource(const std::string& source, const std::string& content)
diff --git a/chrome/browser/extensions/api/page_capture/page_capture_api.cc b/chrome/browser/extensions/api/page_capture/page_capture_api.cc index 262f0e7..21e0e4c 100644 --- a/chrome/browser/extensions/api/page_capture/page_capture_api.cc +++ b/chrome/browser/extensions/api/page_capture/page_capture_api.cc
@@ -55,7 +55,7 @@ // TaskPriority: Inherit. - // TaskShutdownBehavior: TemporaryFileCreated() called from + // TaskShutdownBehavior: TemporaryFileCreated*() called from // CreateTemporaryFile() might access global variable, so use // SKIP_ON_SHUTDOWN. See ShareableFileReference::GetOrCreate(). base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}; @@ -161,26 +161,37 @@ bool success = base::CreateTemporaryFile(&mhtml_path_); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::BindOnce(&PageCaptureSaveAsMHTMLFunction::TemporaryFileCreated, + base::BindOnce(&PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnIO, this, success)); } -void PageCaptureSaveAsMHTMLFunction::TemporaryFileCreated(bool success) { - if (BrowserThread::CurrentlyOn(BrowserThread::IO)) { - if (success) { - // Setup a ShareableFileReference so the temporary file gets deleted - // once it is no longer used. - mhtml_file_ = ShareableFileReference::GetOrCreate( - mhtml_path_, ShareableFileReference::DELETE_ON_FINAL_RELEASE, - BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE).get()); - } - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&PageCaptureSaveAsMHTMLFunction::TemporaryFileCreated, - this, success)); - return; - } +void PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnIO(bool success) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + if (success) { + // Setup a ShareableFileReference so the temporary file gets deleted + // once it is no longer used. + mhtml_file_ = ShareableFileReference::GetOrCreate( + mhtml_path_, ShareableFileReference::DELETE_ON_FINAL_RELEASE, + base::CreateSequencedTaskRunnerWithTraits( + {// Requires IO. + base::MayBlock(), + // TaskPriority: Inherit. + + // Because we are using DELETE_ON_FINAL_RELEASE here, the + // storage::ScopedFile inside ShareableFileReference requires + // a shutdown blocking task runner to ensure that its deletion + // task runs. + base::TaskShutdownBehavior::BLOCK_SHUTDOWN}) + .get()); + } + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnUI, + this, success)); +} + +void PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnUI(bool success) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!success) { ReturnFailure(kTemporaryFileError);
diff --git a/chrome/browser/extensions/api/page_capture/page_capture_api.h b/chrome/browser/extensions/api/page_capture/page_capture_api.h index 1f4f76d..68ff9cb 100644 --- a/chrome/browser/extensions/api/page_capture/page_capture_api.h +++ b/chrome/browser/extensions/api/page_capture/page_capture_api.h
@@ -50,8 +50,10 @@ // Called on the file thread. void CreateTemporaryFile(); + void TemporaryFileCreatedOnIO(bool success); + void TemporaryFileCreatedOnUI(bool success); + // Called on the UI thread. - void TemporaryFileCreated(bool success); void ReturnFailure(const std::string& error); void ReturnSuccess(int64_t file_size);
diff --git a/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc b/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc index 2265088f..ac53115 100644 --- a/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc +++ b/chrome/browser/extensions/bookmark_app_url_redirector_browsertest.cc
@@ -13,26 +13,48 @@ #include "chrome/common/web_application_info.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/notification_service.h" +#include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/notification_types.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "net/test/embedded_test_server/http_response.h" + +using namespace net::test_server; namespace extensions { +const char kLaunchingPagePath[] = + "/extensions/bookmark_apps/url_handlers/launching_pages/index.html"; const char kAppUrlPath[] = "/extensions/bookmark_apps/url_handlers/in_scope/index.html"; const char kScopePath[] = "/extensions/bookmark_apps/url_handlers/in_scope/"; const char kInScopeUrlPath[] = "/extensions/bookmark_apps/url_handlers/in_scope/other.html"; const char kOutOfScopeUrlPath[] = - "/extensions/bookmark_apps/url_handlers/out_of_scope/other.html"; + "/extensions/bookmark_apps/url_handlers/out_of_scope/index.html"; class BookmarkAppUrlRedirectorBrowserTest : public ExtensionBrowserTest { public: + enum class LinkTarget { + SELF, + BLANK, + }; + void SetUp() override { scoped_feature_list_ = base::MakeUnique<base::test::ScopedFeatureList>(); scoped_feature_list_->InitAndEnableFeature(features::kDesktopPWAWindowing); + + // Register a request handler that will return empty pages. Tests are + // responsible for adding elements and firing events on these empty pages. + embedded_test_server()->RegisterRequestHandler( + base::BindRepeating([](const HttpRequest& request) { + auto response = base::MakeUnique<BasicHttpResponse>(); + response->set_content_type("text/html"); + return static_cast<std::unique_ptr<HttpResponse>>( + std::move(response)); + })); + ExtensionBrowserTest::SetUp(); } @@ -67,6 +89,37 @@ return chrome::FindLastActive(); } + // Navigates the active tab to the launching page. + void NavigateToLaunchingPage() { + GURL launching_page_url = + embedded_test_server()->GetURL(kLaunchingPagePath); + ui_test_utils::UrlLoadObserver url_observer( + launching_page_url, content::NotificationService::AllSources()); + ui_test_utils::NavigateToURL(browser(), launching_page_url); + url_observer.Wait(); + } + + // Creates an <a> element, sets its href and target to |href| and |target| + // respectively, adds it to the DOM, and clicks on it. Returns once the link + // has loaded. + void ClickLinkAndWait(content::WebContents* web_contents, + const std::string& href, + LinkTarget target) { + ui_test_utils::UrlLoadObserver url_observer( + embedded_test_server()->GetURL(href), + content::NotificationService::AllSources()); + std::string script = base::StringPrintf( + "const link = document.createElement('a');" + "link.href = '%s';" + "link.target = '%s';" + "document.body.appendChild(link);" + "const event = new MouseEvent('click', {'view': window});" + "link.dispatchEvent(event);", + href.c_str(), target == LinkTarget::SELF ? "_self" : "_blank"); + EXPECT_TRUE(content::ExecuteScript(web_contents, script)); + url_observer.Wait(); + } + void ResetFeatureList() { scoped_feature_list_.reset(); } private: @@ -79,24 +132,21 @@ FeatureDisable_BeforeInstall) { ResetFeatureList(); InstallTestBookmarkApp(); + NavigateToLaunchingPage(); + content::WebContents* initial_tab = + browser()->tab_strip_model()->GetActiveWebContents(); int num_tabs = browser()->tab_strip_model()->count(); size_t num_browsers = chrome::GetBrowserCount(profile()); - GURL app_url = embedded_test_server()->GetURL(kAppUrlPath); - ui_test_utils::UrlLoadObserver url_observer( - app_url, content::NotificationService::AllSources()); - ui_test_utils::NavigateToURL(browser(), app_url); - url_observer.Wait(); + ClickLinkAndWait(initial_tab, kAppUrlPath, LinkTarget::SELF); EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); EXPECT_EQ(browser(), chrome::FindLastActive()); - EXPECT_EQ(app_url, browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL()); + EXPECT_EQ(embedded_test_server()->GetURL(kAppUrlPath), + initial_tab->GetLastCommittedURL()); } // Tests that navigating to the Web App's app_url doesn't open a new window @@ -105,154 +155,133 @@ FeatureDisable_AfterInstall) { InstallTestBookmarkApp(); ResetFeatureList(); + NavigateToLaunchingPage(); + content::WebContents* initial_tab = + browser()->tab_strip_model()->GetActiveWebContents(); int num_tabs = browser()->tab_strip_model()->count(); size_t num_browsers = chrome::GetBrowserCount(profile()); - GURL app_url = embedded_test_server()->GetURL(kAppUrlPath); - ui_test_utils::UrlLoadObserver url_observer( - app_url, content::NotificationService::AllSources()); - ui_test_utils::NavigateToURL(browser(), app_url); - url_observer.Wait(); + ClickLinkAndWait(initial_tab, kAppUrlPath, LinkTarget::SELF); EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); EXPECT_EQ(browser(), chrome::FindLastActive()); - EXPECT_EQ(app_url, browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL()); + EXPECT_EQ(embedded_test_server()->GetURL(kAppUrlPath), + initial_tab->GetLastCommittedURL()); } -// Tests that navigating to the Web App's app_url opens a new browser window. +// Tests that clicking a link with target="_self" to the apps app_url opens the +// Bookmark App. IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, AppUrl) { InstallTestBookmarkApp(); + NavigateToLaunchingPage(); + content::WebContents* initial_tab = + browser()->tab_strip_model()->GetActiveWebContents(); + GURL initial_url = initial_tab->GetLastCommittedURL(); int num_tabs = browser()->tab_strip_model()->count(); size_t num_browsers = chrome::GetBrowserCount(profile()); - GURL initial_url = browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL(); - GURL app_url = embedded_test_server()->GetURL(kAppUrlPath); - ui_test_utils::UrlLoadObserver url_observer( - app_url, content::NotificationService::AllSources()); - ui_test_utils::NavigateToURL(browser(), app_url); - url_observer.Wait(); + ClickLinkAndWait(initial_tab, kAppUrlPath, LinkTarget::SELF); EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); EXPECT_EQ(++num_browsers, chrome::GetBrowserCount(profile())); EXPECT_NE(browser(), chrome::FindLastActive()); - EXPECT_EQ(initial_url, browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL()); - EXPECT_EQ(app_url, chrome::FindLastActive() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL()); + EXPECT_EQ(initial_url, initial_tab->GetLastCommittedURL()); + EXPECT_EQ(embedded_test_server()->GetURL(kAppUrlPath), + chrome::FindLastActive() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL()); } -// Tests that navigating to a URL in the Web App's scope opens a new browser -// window. +// Tests that clicking a link with target="_self" to a URL in the Web App's +// scope opens a new browser window. IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, InScopeUrl) { InstallTestBookmarkApp(); + NavigateToLaunchingPage(); + content::WebContents* initial_tab = + browser()->tab_strip_model()->GetActiveWebContents(); + GURL initial_url = initial_tab->GetLastCommittedURL(); int num_tabs = browser()->tab_strip_model()->count(); size_t num_browsers = chrome::GetBrowserCount(profile()); - GURL initial_url = browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL(); - GURL in_scope_url = embedded_test_server()->GetURL(kInScopeUrlPath); - ui_test_utils::UrlLoadObserver url_observer( - in_scope_url, content::NotificationService::AllSources()); - ui_test_utils::NavigateToURL(browser(), in_scope_url); - url_observer.Wait(); + ClickLinkAndWait(initial_tab, kInScopeUrlPath, LinkTarget::SELF); EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); EXPECT_EQ(++num_browsers, chrome::GetBrowserCount(profile())); EXPECT_NE(browser(), chrome::FindLastActive()); - EXPECT_EQ(initial_url, browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL()); - EXPECT_EQ(in_scope_url, chrome::FindLastActive() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL()); + EXPECT_EQ(initial_url, initial_tab->GetLastCommittedURL()); + EXPECT_EQ(embedded_test_server()->GetURL(kInScopeUrlPath), + chrome::FindLastActive() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL()); } -// Tests that navigating to a URL out of the Web App's scope but with the -// same origin doesn't open a new browser window. +// Tests that clicking a link with target="_self" to a URL out of the Web App's +// scope but with the same origin doesn't open a new browser window. IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, OutOfScopeUrl) { InstallTestBookmarkApp(); + NavigateToLaunchingPage(); int num_tabs = browser()->tab_strip_model()->count(); size_t num_browsers = chrome::GetBrowserCount(profile()); - GURL out_of_scope_url = embedded_test_server()->GetURL(kOutOfScopeUrlPath); - ui_test_utils::UrlLoadObserver url_observer( - out_of_scope_url, content::NotificationService::AllSources()); - ui_test_utils::NavigateToURL(browser(), out_of_scope_url); - url_observer.Wait(); + ClickLinkAndWait(browser()->tab_strip_model()->GetActiveWebContents(), + kOutOfScopeUrlPath, LinkTarget::SELF); EXPECT_EQ(num_tabs, browser()->tab_strip_model()->count()); EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); EXPECT_EQ(browser(), chrome::FindLastActive()); - EXPECT_EQ(out_of_scope_url, chrome::FindLastActive() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL()); + EXPECT_EQ(embedded_test_server()->GetURL(kOutOfScopeUrlPath), + chrome::FindLastActive() + ->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL()); } -// Tests that navigating inside the app doesn't open new browser windows. +// Tests that clicking links inside the app doesn't open new browser windows. IN_PROC_BROWSER_TEST_F(BookmarkAppUrlRedirectorBrowserTest, InAppNavigation) { InstallTestBookmarkApp(); Browser* app_browser = OpenTestBookmarkApp(); + content::WebContents* app_web_contents = + app_browser->tab_strip_model()->GetActiveWebContents(); int num_tabs_browser = browser()->tab_strip_model()->count(); int num_tabs_app_browser = app_browser->tab_strip_model()->count(); size_t num_browsers = chrome::GetBrowserCount(profile()); { - GURL in_scope_url = embedded_test_server()->GetURL(kInScopeUrlPath); - ui_test_utils::UrlLoadObserver url_observer( - in_scope_url, content::NotificationService::AllSources()); - ui_test_utils::NavigateToURL(app_browser, in_scope_url); - url_observer.Wait(); + ClickLinkAndWait(app_web_contents, kInScopeUrlPath, LinkTarget::SELF); EXPECT_EQ(num_tabs_browser, browser()->tab_strip_model()->count()); EXPECT_EQ(num_tabs_app_browser, app_browser->tab_strip_model()->count()); EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); EXPECT_EQ(app_browser, chrome::FindLastActive()); - EXPECT_EQ(in_scope_url, app_browser->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL()); + EXPECT_EQ(embedded_test_server()->GetURL(kInScopeUrlPath), + app_web_contents->GetLastCommittedURL()); } { - GURL out_of_scope_url = embedded_test_server()->GetURL(kOutOfScopeUrlPath); - ui_test_utils::UrlLoadObserver url_observer( - out_of_scope_url, content::NotificationService::AllSources()); - ui_test_utils::NavigateToURL(app_browser, out_of_scope_url); - url_observer.Wait(); + ClickLinkAndWait(app_web_contents, kOutOfScopeUrlPath, LinkTarget::SELF); EXPECT_EQ(num_tabs_browser, browser()->tab_strip_model()->count()); EXPECT_EQ(num_tabs_app_browser, app_browser->tab_strip_model()->count()); EXPECT_EQ(num_browsers, chrome::GetBrowserCount(profile())); EXPECT_EQ(app_browser, chrome::FindLastActive()); - EXPECT_EQ(out_of_scope_url, app_browser->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL()); + EXPECT_EQ(embedded_test_server()->GetURL(kOutOfScopeUrlPath), + app_browser->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL()); } }
diff --git a/chrome/browser/media/webrtc/desktop_media_list_ash.cc b/chrome/browser/media/webrtc/desktop_media_list_ash.cc index d37717d..c5763fb 100644 --- a/chrome/browser/media/webrtc/desktop_media_list_ash.cc +++ b/chrome/browser/media/webrtc/desktop_media_list_ash.cc
@@ -6,7 +6,6 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/shell.h" -#include "base/task_scheduler/post_task.h" #include "chrome/grit/generated_resources.h" #include "media/base/video_util.h" #include "ui/base/l10n/l10n_util.h" @@ -25,8 +24,6 @@ DesktopMediaListAsh::DesktopMediaListAsh(content::DesktopMediaID::Type type) : DesktopMediaListBase( base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)), - background_task_runner_(base::CreateTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::USER_BLOCKING})), weak_factory_(this) { DCHECK(type == content::DesktopMediaID::TYPE_SCREEN || type == content::DesktopMediaID::TYPE_WINDOW); @@ -122,7 +119,7 @@ ++pending_window_capture_requests_; ui::GrabWindowSnapshotAndScaleAsync( - window, window_rect, scaled_rect.size(), background_task_runner_, + window, window_rect, scaled_rect.size(), base::Bind(&DesktopMediaListAsh::OnThumbnailCaptured, weak_factory_.GetWeakPtr(), id)); }
diff --git a/chrome/browser/media/webrtc/desktop_media_list_ash.h b/chrome/browser/media/webrtc/desktop_media_list_ash.h index 6136dac..3ed50caa 100644 --- a/chrome/browser/media/webrtc/desktop_media_list_ash.h +++ b/chrome/browser/media/webrtc/desktop_media_list_ash.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_MEDIA_WEBRTC_DESKTOP_MEDIA_LIST_ASH_H_ #define CHROME_BROWSER_MEDIA_WEBRTC_DESKTOP_MEDIA_LIST_ASH_H_ +#include <vector> + #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "chrome/browser/media/webrtc/desktop_media_list_base.h" @@ -14,10 +16,6 @@ class Window; } -namespace base { -class TaskRunner; -} - namespace gfx { class Image; } @@ -44,9 +42,6 @@ int pending_window_capture_requests_ = 0; - // Used to scale the thumbnails. - scoped_refptr<base::TaskRunner> background_task_runner_; - SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory<DesktopMediaListAsh> weak_factory_;
diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.cc b/chrome/browser/media/webrtc/native_desktop_media_list.cc index ae12993..a459941 100644 --- a/chrome/browser/media/webrtc/native_desktop_media_list.cc +++ b/chrome/browser/media/webrtc/native_desktop_media_list.cc
@@ -325,8 +325,6 @@ pending_aura_capture_requests_++; ui::GrabWindowSnapshotAndScaleAsyncAura( window, window_rect, scaled_rect.size(), - base::CreateTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::USER_VISIBLE}), base::Bind(&NativeDesktopMediaList::OnAuraThumbnailCaptured, weak_factory_.GetWeakPtr(), id)); }
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.cc b/chrome/browser/push_messaging/push_messaging_service_impl.cc index b2262302..82ef198 100644 --- a/chrome/browser/push_messaging/push_messaging_service_impl.cc +++ b/chrome/browser/push_messaging/push_messaging_service_impl.cc
@@ -359,7 +359,8 @@ switches::kAllowSilentPush)) { notification_manager_.EnforceUserVisibleOnlyRequirements( requesting_origin, service_worker_registration_id, - completion_closure_runner.Release()); + base::AdaptCallbackForRepeating( + completion_closure_runner.Release())); } break; case content::mojom::PushDeliveryStatus::SERVICE_WORKER_ERROR: @@ -390,7 +391,8 @@ : app_identifier.service_worker_registration_id(), app_id, message.sender_id, base::Bind(&UnregisterCallbackToClosure, - completion_closure_runner.Release())); + base::AdaptCallbackForRepeating( + completion_closure_runner.Release()))); } }
diff --git a/chrome/browser/resources/chromeos/login/md_login_shared.js b/chrome/browser/resources/chromeos/login/md_login_shared.js index 6d16fd00..15132c0 100644 --- a/chrome/browser/resources/chromeos/login/md_login_shared.js +++ b/chrome/browser/resources/chromeos/login/md_login_shared.js
@@ -426,12 +426,6 @@ Oobe.setVirtualKeyboardShown = function(shown) { Oobe.getInstance().virtualKeyboardShown = shown; $('pod-row').setFocusedPodPinVisibility(!shown); - // The dark overlay should always have the same size with the larger one - // of the outer-container and the scroll-container. - if (shown) - $('login-shield').style.minHeight = $('outer-container').style.minHeight; - else - $('login-shield').style.minHeight = 'unset'; }; /**
diff --git a/chrome/browser/resources/chromeos/login/md_screen_container.html b/chrome/browser/resources/chromeos/login/md_screen_container.html index 0cc2640..592cb26 100644 --- a/chrome/browser/resources/chromeos/login/md_screen_container.html +++ b/chrome/browser/resources/chromeos/login/md_screen_container.html
@@ -1,7 +1,6 @@ <div id="background" class="background-initial"></div> <include src="api_keys_notice.html"> <div id="scroll-container"> - <div id="login-shield"></div> <div id="outer-container" class="down"> <div id="oobe" class="faded"> <div id="inner-container" class="down">
diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js index 13a3b8b..e11aaaa6 100644 --- a/chrome/browser/resources/chromeos/login/oobe.js +++ b/chrome/browser/resources/chromeos/login/oobe.js
@@ -382,16 +382,11 @@ setMDMode_: function() { if (loadTimeData.getString('newOobeUI') == 'on') { $('oobe').setAttribute('md-mode', 'true'); - $('oobe-shield').setAttribute('md-mode', 'true'); $('popup-overlay').setAttribute('md-mode', 'true'); } else { $('oobe').removeAttribute('md-mode'); - $('oobe-shield').removeAttribute('md-mode'); $('popup-overlay').removeAttribute('md-mode'); } - - $('oobe-shield').hidden = - (loadTimeData.getString('hideOobeShield') == 'on'); }, }; });
diff --git a/chrome/browser/resources/chromeos/login/screen_container.html b/chrome/browser/resources/chromeos/login/screen_container.html index 9a58114..407e0a2 100644 --- a/chrome/browser/resources/chromeos/login/screen_container.html +++ b/chrome/browser/resources/chromeos/login/screen_container.html
@@ -1,7 +1,6 @@ <div id="background" class="background-initial"></div> <include src="api_keys_notice.html"> <div id="scroll-container"> - <div id="oobe-shield"></div> <div id="outer-container" class="down"> <div id="oobe" class="faded"> <div id="inner-container" class="down">
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.css b/chrome/browser/resources/chromeos/login/screen_gaia_signin.css index b1db31b3..8ec5946 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.css +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.css
@@ -129,3 +129,8 @@ #gaia-signin:not(.v2) #signin-frame-dialog { display: none; } + +#gaia-signin.v2.saml #signin-frame { + height: 516px; + padding-top: 44px; +}
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js index 1965bba..9204c66 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
@@ -774,6 +774,7 @@ this.classList.toggle('full-width', isSAML); $('saml-notice-container').hidden = !isSAML; + this.classList.toggle('saml', isSAML); if (Oobe.getInstance().currentScreen === this) { Oobe.getInstance().updateScreenSize(this); @@ -1178,6 +1179,11 @@ var isManaged = opt_data && opt_data.enterpriseManaged; $('gaia-whitelist-error').textContent = loadTimeData.getValue( isManaged ? 'whitelistErrorEnterprise' : 'whitelistErrorConsumer'); + // To make animations correct, we need to make sure Gaia is completely + // reloaded. Otherwise ChromeOS overlays hide and Gaia page is shown + // somewhere in the middle of animations. + if (this.screenMode_ == ScreenMode.DEFAULT) + this.gaiaAuthHost_.resetWebview(); } this.classList.toggle('whitelist-error', show);
diff --git a/chrome/browser/resources/md_extensions/.eslintrc.js b/chrome/browser/resources/md_extensions/.eslintrc.js new file mode 100644 index 0000000..847d6e995 --- /dev/null +++ b/chrome/browser/resources/md_extensions/.eslintrc.js
@@ -0,0 +1,13 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module.exports = { + 'env': { + 'browser': true, + 'es6': true, + }, + 'rules': { + 'no-var': 'error', + }, +};
diff --git a/chrome/browser/resources/md_extensions/animation_helper.js b/chrome/browser/resources/md_extensions/animation_helper.js index 00483b37..1266b7c 100644 --- a/chrome/browser/resources/md_extensions/animation_helper.js +++ b/chrome/browser/resources/md_extensions/animation_helper.js
@@ -41,7 +41,7 @@ * @param {!Array<extensions.Animation>} animations */ setEntryAnimations(animations) { - var configs = []; + const configs = []; for (let animation of animations) { switch (animation) { case extensions.Animation.HERO: @@ -64,7 +64,7 @@ * @param {!Array<extensions.Animation>} animations */ setExitAnimations(animations) { - var configs = []; + const configs = []; for (let animation of animations) { switch (animation) { case extensions.Animation.HERO:
diff --git a/chrome/browser/resources/md_extensions/code_section.js b/chrome/browser/resources/md_extensions/code_section.js index d2f4e8f..1ea32d7 100644 --- a/chrome/browser/resources/md_extensions/code_section.js +++ b/chrome/browser/resources/md_extensions/code_section.js
@@ -5,7 +5,7 @@ cr.define('extensions', function() { 'use strict'; - var CodeSection = Polymer({ + const CodeSection = Polymer({ is: 'extensions-code-section', properties: { @@ -49,12 +49,12 @@ if (!this.code) return ''; - var lines = [ + const lines = [ this.code.beforeHighlight, this.code.highlight, this.code.afterHighlight ].join('').match(/\n/g); - var lineCount = lines ? lines.length : 0; - var textContent = ''; - for (var i = 1; i <= lineCount; ++i) + const lineCount = lines ? lines.length : 0; + let textContent = ''; + for (let i = 1; i <= lineCount; ++i) textContent += i + '\n'; return textContent; },
diff --git a/chrome/browser/resources/md_extensions/detail_view.js b/chrome/browser/resources/md_extensions/detail_view.js index b424760..d01d4e4 100644 --- a/chrome/browser/resources/md_extensions/detail_view.js +++ b/chrome/browser/resources/md_extensions/detail_view.js
@@ -5,7 +5,7 @@ cr.define('extensions', function() { 'use strict'; - var DetailView = Polymer({ + const DetailView = Polymer({ is: 'extensions-detail-view', behaviors: [I18nBehavior, Polymer.NeonAnimatableBehavior],
diff --git a/chrome/browser/resources/md_extensions/drop_overlay.js b/chrome/browser/resources/md_extensions/drop_overlay.js index f19653de..feeddba5 100644 --- a/chrome/browser/resources/md_extensions/drop_overlay.js +++ b/chrome/browser/resources/md_extensions/drop_overlay.js
@@ -9,7 +9,7 @@ is: 'extensions-drop-overlay', created: function() { this.hidden = true; - var dragTarget = document.documentElement; + const dragTarget = document.documentElement; this.dragWrapperHandler_ = new extensions.DragAndDropHandler(true, dragTarget); dragTarget.addEventListener('extension-drag-started', () => {
diff --git a/chrome/browser/resources/md_extensions/error_page.js b/chrome/browser/resources/md_extensions/error_page.js index 90ffaf33..4025e1b 100644 --- a/chrome/browser/resources/md_extensions/error_page.js +++ b/chrome/browser/resources/md_extensions/error_page.js
@@ -3,15 +3,15 @@ // found in the LICENSE file. /** @typedef {chrome.developerPrivate.ManifestError} */ -var ManifestError; +let ManifestError; /** @typedef {chrome.developerPrivate.RuntimeError} */ -var RuntimeError; +let RuntimeError; cr.define('extensions', function() { 'use strict'; /** @interface */ - var ErrorPageDelegate = function() {}; + const ErrorPageDelegate = function() {}; ErrorPageDelegate.prototype = { /** @@ -28,7 +28,7 @@ requestFileSource: assertNotReached, }; - var ErrorPage = Polymer({ + const ErrorPage = Polymer({ is: 'extensions-error-page', behaviors: [Polymer.NeonAnimatableBehavior], @@ -64,7 +64,7 @@ */ observeDataChanges_: function() { assert(this.data); - var e = this.data.manifestErrors[0] || this.data.runtimeErrors[0]; + const e = this.data.manifestErrors[0] || this.data.runtimeErrors[0]; if (e) this.selectedError_ = e; }, @@ -110,7 +110,7 @@ onDeleteErrorTap_: function(event) { // TODO(devlin): It would be cleaner if we could cast this to a // PolymerDomRepeatEvent-type thing, but that doesn't exist yet. - var e = /** @type {!{model:Object}} */ (event); + const e = /** @type {!{model:Object}} */ (event); this.delegate.deleteErrors(this.data.id, [e.model.item.id]); }, @@ -119,8 +119,8 @@ * @private */ onSelectedErrorChanged_: function() { - var error = this.selectedError_; - var args = { + const error = this.selectedError_; + const args = { extensionId: error.extensionId, message: error.message, };
diff --git a/chrome/browser/resources/md_extensions/extensions.js b/chrome/browser/resources/md_extensions/extensions.js index 5b5cfd2..a9a6265 100644 --- a/chrome/browser/resources/md_extensions/extensions.js +++ b/chrome/browser/resources/md_extensions/extensions.js
@@ -4,7 +4,7 @@ (function() { 'use strict'; -var manager = /** @type {extensions.Manager} */ ( +const manager = /** @type {extensions.Manager} */ ( document.querySelector('extensions-manager')); manager.readyPromiseResolver.promise.then(function() { extensions.Service.getInstance().managerReady(manager);
diff --git a/chrome/browser/resources/md_extensions/item.js b/chrome/browser/resources/md_extensions/item.js index aa5aa829..9968073 100644 --- a/chrome/browser/resources/md_extensions/item.js +++ b/chrome/browser/resources/md_extensions/item.js
@@ -4,7 +4,7 @@ cr.define('extensions', function() { /** @interface */ - var ItemDelegate = function() {}; + const ItemDelegate = function() {}; ItemDelegate.prototype = { /** @param {string} id */ @@ -56,7 +56,7 @@ showItemOptionsPage: assertNotReached, }; - var Item = Polymer({ + const Item = Polymer({ is: 'extensions-item', behaviors: [I18nBehavior], @@ -95,7 +95,7 @@ /** @private */ observeIdVisibility_: function(inDevMode, showingDetails, id) { Polymer.dom.flush(); - var idElement = this.$$('#extension-id'); + const idElement = this.$$('#extension-id'); if (idElement) { assert(this.data); idElement.innerHTML = this.i18n('itemId', this.data.id); @@ -204,7 +204,7 @@ * @private */ computeClasses_: function() { - var classes = this.isEnabled_() ? 'enabled' : 'disabled'; + let classes = this.isEnabled_() ? 'enabled' : 'disabled'; if (this.inDevMode) classes += ' dev-mode'; return classes; @@ -233,7 +233,7 @@ * @private */ computeSourceIndicatorText_: function() { - var sourceType = extensions.getItemSource(this.data); + const sourceType = extensions.getItemSource(this.data); return sourceType == SourceType.WEBSTORE ? '' : extensions.getItemSourceString(sourceType); @@ -259,7 +259,7 @@ // need to handle the case gracefully. if (this.data.views.length == 0) return ''; - var label = extensions.computeInspectableViewLabel(this.data.views[0]); + let label = extensions.computeInspectableViewLabel(this.data.views[0]); if (this.data.views.length > 1) label += ','; return label; @@ -281,7 +281,7 @@ // Only display the reload spinner if the extension is unpacked and // not terminated (since if it's terminated, we'll show a crashed reload // buton). - var showIcon = + const showIcon = this.data.location == chrome.developerPrivate.Location.UNPACKED && this.data.state != chrome.developerPrivate.ExtensionState.TERMINATED; return !showIcon;
diff --git a/chrome/browser/resources/md_extensions/item_list.js b/chrome/browser/resources/md_extensions/item_list.js index a545b82e..eaa07793 100644 --- a/chrome/browser/resources/md_extensions/item_list.js +++ b/chrome/browser/resources/md_extensions/item_list.js
@@ -3,7 +3,7 @@ // found in the LICENSE file. cr.define('extensions', function() { - var ItemList = Polymer({ + const ItemList = Polymer({ is: 'extensions-item-list', behaviors: [Polymer.NeonAnimatableBehavior, Polymer.IronResizableBehavior],
diff --git a/chrome/browser/resources/md_extensions/item_util.js b/chrome/browser/resources/md_extensions/item_util.js index a112340..8a65d2c 100644 --- a/chrome/browser/resources/md_extensions/item_util.js +++ b/chrome/browser/resources/md_extensions/item_util.js
@@ -4,7 +4,7 @@ // Closure compiler won't let this be declared inside cr.define(). /** @enum {string} */ -var SourceType = { +const SourceType = { WEBSTORE: 'webstore', POLICY: 'policy', SIDELOADED: 'sideloaded', @@ -106,8 +106,8 @@ */ function computeInspectableViewLabel(view) { // Trim the "chrome-extension://<id>/". - var url = new URL(view.url); - var label = view.url; + const url = new URL(view.url); + let label = view.url; if (url.protocol == 'chrome-extension:') label = url.pathname.substring(1); if (label == '_generated_background_page.html')
diff --git a/chrome/browser/resources/md_extensions/keyboard_shortcuts.js b/chrome/browser/resources/md_extensions/keyboard_shortcuts.js index 1490eeb..850dfc3 100644 --- a/chrome/browser/resources/md_extensions/keyboard_shortcuts.js +++ b/chrome/browser/resources/md_extensions/keyboard_shortcuts.js
@@ -6,7 +6,7 @@ 'use strict'; // The UI to display and manage keyboard shortcuts set for extension commands. - var KeyboardShortcuts = Polymer({ + const KeyboardShortcuts = Polymer({ is: 'extensions-keyboard-shortcuts', behaviors: [Polymer.NeonAnimatableBehavior], @@ -21,7 +21,7 @@ */ CommandScope_: { type: Object, - value: chrome.developerPrivate.CommandScope + value: chrome.developerPrivate.CommandScope, }, },
diff --git a/chrome/browser/resources/md_extensions/load_error.js b/chrome/browser/resources/md_extensions/load_error.js index bd440713..5d1cc8e 100644 --- a/chrome/browser/resources/md_extensions/load_error.js +++ b/chrome/browser/resources/md_extensions/load_error.js
@@ -16,7 +16,7 @@ retryLoadUnpacked: assertNotReached, }; - var LoadError = Polymer({ + const LoadError = Polymer({ is: 'extensions-load-error', properties: { /** @type {extensions.LoadErrorDelegate} */ @@ -47,12 +47,12 @@ /** @private */ observeLoadErrorChanges_: function() { assert(this.loadError); - var source = this.loadError.source; + const source = this.loadError.source; // CodeSection expects a RequestFileSourceResponse, rather than an // ErrorFileSource. Massage into place. // TODO(devlin): Make RequestFileSourceResponse use ErrorFileSource. /** @type {!chrome.developerPrivate.RequestFileSourceResponse} */ - var codeSectionProperties = { + const codeSectionProperties = { beforeHighlight: source ? source.beforeHighlight : '', highlight: source ? source.highlight : '', afterHighlight: source ? source.afterHighlight : '',
diff --git a/chrome/browser/resources/md_extensions/manager.js b/chrome/browser/resources/md_extensions/manager.js index 48cc47d..0f515ce 100644 --- a/chrome/browser/resources/md_extensions/manager.js +++ b/chrome/browser/resources/md_extensions/manager.js
@@ -11,7 +11,7 @@ * @param {chrome.developerPrivate.ExtensionInfo} b * @return {number} */ - var compareExtensions = function(a, b) { + const compareExtensions = function(a, b) { function compare(x, y) { return x < y ? -1 : (x > y ? 1 : 0); } @@ -29,7 +29,7 @@ compare(a.id, b.id); }; - var Manager = Polymer({ + const Manager = Polymer({ is: 'extensions-manager', behaviors: [I18nBehavior], @@ -203,8 +203,8 @@ * @private */ getListId_: function(type) { - var listId; - var ExtensionType = chrome.developerPrivate.ExtensionType; + let listId; + const ExtensionType = chrome.developerPrivate.ExtensionType; switch (type) { case ExtensionType.HOSTED_APP: case ExtensionType.LEGACY_PACKAGED_APP: @@ -252,10 +252,10 @@ * the new element is representing. */ addItem: function(item) { - var listId = this.getListId_(item.type); + const listId = this.getListId_(item.type); // We should never try and add an existing item. assert(this.getIndexInList_(listId, item.id) == -1); - var insertBeforeChild = this[listId].findIndex(function(listEl) { + let insertBeforeChild = this[listId].findIndex(function(listEl) { return compareExtensions(listEl, item) > 0; }); if (insertBeforeChild == -1) @@ -268,8 +268,8 @@ * item to update. */ updateItem: function(item) { - var listId = this.getListId_(item.type); - var index = this.getIndexInList_(listId, item.id); + const listId = this.getListId_(item.type); + const index = this.getIndexInList_(listId, item.id); // We should never try and update a non-existent item. assert(index >= 0); this.set([listId, index], item); @@ -294,8 +294,8 @@ * item to remove. */ removeItem: function(item) { - var listId = this.getListId_(item.type); - var index = this.getIndexInList_(listId, item.id); + const listId = this.getListId_(item.type); + const index = this.getIndexInList_(listId, item.id); // We should never try and remove a non-existent item. assert(index >= 0); this.splice(listId, index, 1); @@ -339,9 +339,9 @@ if (this.optionsDialog.open) this.optionsDialog.close(); - var fromPage = this.$.pages.selected; - var toPage = newPage.page; - var data; + const fromPage = this.$.pages.selected; + const toPage = newPage.page; + let data; if (newPage.extensionId) data = assert(this.getData_(newPage.extensionId)); @@ -351,8 +351,8 @@ this.errorPageItem_ = assert(data); if (fromPage != toPage) { - var entry; - var exit; + let entry; + let exit; if (fromPage == Page.LIST && (toPage == Page.DETAILS || toPage == Page.ERRORS)) { this.$['items-list'].willShowItemSubpage(data.id); @@ -433,7 +433,7 @@ /** @override */ showType(type) { - var items; + let items; switch (type) { case extensions.ShowingType.EXTENSIONS: items = this.manager_.extensions;
diff --git a/chrome/browser/resources/md_extensions/navigation_helper.js b/chrome/browser/resources/md_extensions/navigation_helper.js index d15ca5996..c5272a6 100644 --- a/chrome/browser/resources/md_extensions/navigation_helper.js +++ b/chrome/browser/resources/md_extensions/navigation_helper.js
@@ -7,7 +7,7 @@ * Note: This must remain in sync with the page ids in manager.html! * @enum {string} */ -var Page = { +const Page = { LIST: 'items-list', DETAILS: 'details-view', SHORTCUTS: 'keyboard-shortcuts', @@ -15,14 +15,14 @@ }; /** @enum {string} */ -var Dialog = { +const Dialog = { OPTIONS: 'options', }; /** @typedef {{page: Page, extensionId: (string|undefined), subpage: (!Dialog|undefined)}} */ -var PageState; +let PageState; cr.define('extensions', function() { 'use strict'; @@ -53,8 +53,8 @@ * URL. */ getCurrentPage() { - var search = new URLSearchParams(location.search); - var id = search.get('id'); + const search = new URLSearchParams(location.search); + let id = search.get('id'); if (id) return {page: Page.DETAILS, extensionId: id}; id = search.get('options'); @@ -75,7 +75,7 @@ * @param {!PageState} entry */ updateHistory(entry) { - var path; + let path; switch (entry.page) { case Page.LIST: path = '/'; @@ -96,9 +96,9 @@ break; } assert(path); - var state = {url: path}; - var currentPage = this.getCurrentPage(); - var isDialogNavigation = currentPage.page == entry.page && + const state = {url: path}; + const currentPage = this.getCurrentPage(); + const isDialogNavigation = currentPage.page == entry.page && currentPage.extensionId == entry.extensionId; // Navigating to a dialog doesn't visually change pages; it just opens // a dialog. As such, we replace state rather than pushing a new state
diff --git a/chrome/browser/resources/md_extensions/options_dialog.js b/chrome/browser/resources/md_extensions/options_dialog.js index fe00579..eaed4c9 100644 --- a/chrome/browser/resources/md_extensions/options_dialog.js +++ b/chrome/browser/resources/md_extensions/options_dialog.js
@@ -5,14 +5,14 @@ cr.define('extensions', function() { 'use strict'; - var MAX_HEIGHT = 600; - var MAX_WIDTH = 600; - var MIN_HEIGHT = 300; - var MIN_WIDTH = 300; - var HEADER_EXTRA_SPACING = 50; // 40 from x-button + 10 from img margin. - var DIALOG_PADDING = 32; // Padding from cr-dialog's .body styling. + const MAX_HEIGHT = 600; + const MAX_WIDTH = 600; + const MIN_HEIGHT = 300; + const MIN_WIDTH = 300; + const HEADER_EXTRA_SPACING = 50; // 40 from x-button + 10 from img margin. + const DIALOG_PADDING = 32; // Padding from cr-dialog's .body styling. - var OptionsDialog = Polymer({ + const OptionsDialog = Polymer({ is: 'extensions-options-dialog', properties: { /** @private {Object} */ @@ -33,15 +33,16 @@ this.extensionOptions_ = document.createElement('ExtensionOptions'); this.extensionOptions_.extension = this.data_.id; this.extensionOptions_.onclose = this.close.bind(this); - var bounded = function(min, max, val) { + const bounded = function(min, max, val) { return Math.min(Math.max(min, val), max); }; - var onSizeChanged = e => { - var minHeaderWidth = this.$$('#icon-and-name-wrapper img').offsetWidth + + const onSizeChanged = e => { + const minHeaderWidth = + this.$$('#icon-and-name-wrapper img').offsetWidth + this.$$('#icon-and-name-wrapper span').offsetWidth + HEADER_EXTRA_SPACING; - var minWidth = Math.max(minHeaderWidth, MIN_WIDTH); + const minWidth = Math.max(minHeaderWidth, MIN_WIDTH); this.extensionOptions_.style.height = bounded(MIN_HEIGHT, MAX_HEIGHT, e.height) + 'px'; this.extensionOptions_.style.width =
diff --git a/chrome/browser/resources/md_extensions/pack_dialog.js b/chrome/browser/resources/md_extensions/pack_dialog.js index c6c527fa..2f8ac64 100644 --- a/chrome/browser/resources/md_extensions/pack_dialog.js +++ b/chrome/browser/resources/md_extensions/pack_dialog.js
@@ -33,7 +33,7 @@ packExtension: assertNotReached, }; - var PackDialog = Polymer({ + const PackDialog = Polymer({ is: 'extensions-pack-dialog', properties: { /** @type {extensions.PackDialogDelegate} */
diff --git a/chrome/browser/resources/md_extensions/pack_dialog_alert.js b/chrome/browser/resources/md_extensions/pack_dialog_alert.js index 619dd80..3afe8734 100644 --- a/chrome/browser/resources/md_extensions/pack_dialog_alert.js +++ b/chrome/browser/resources/md_extensions/pack_dialog_alert.js
@@ -5,7 +5,7 @@ cr.define('extensions', function() { 'use strict'; - var PackDialogAlert = Polymer({ + const PackDialogAlert = Polymer({ is: 'extensions-pack-dialog-alert', properties: { /** @private {chrome.developerPrivate.PackDirectoryResponse} */
diff --git a/chrome/browser/resources/md_extensions/service.js b/chrome/browser/resources/md_extensions/service.js index 722f8019..24a7130 100644 --- a/chrome/browser/resources/md_extensions/service.js +++ b/chrome/browser/resources/md_extensions/service.js
@@ -29,7 +29,7 @@ this.manager_ = manager; this.manager_.set('delegate', this); - var keyboardShortcuts = this.manager_.keyboardShortcuts; + const keyboardShortcuts = this.manager_.keyboardShortcuts; keyboardShortcuts.addEventListener( 'shortcut-updated', this.onExtensionCommandUpdated_.bind(this)); keyboardShortcuts.addEventListener( @@ -67,11 +67,11 @@ * @private */ onItemStateChanged_(eventData) { - var currentIndex = this.extensions_.findIndex(function(extension) { + const currentIndex = this.extensions_.findIndex(function(extension) { return extension.id == eventData.item_id; }); - var EventType = chrome.developerPrivate.EventType; + const EventType = chrome.developerPrivate.EventType; switch (eventData.event_type) { case EventType.VIEW_REGISTERED: case EventType.VIEW_UNREGISTERED: @@ -248,7 +248,7 @@ /** @override */ showItemOptionsPage(id) { - var extension = this.extensions_.find(function(e) { + const extension = this.extensions_.find(function(e) { return e.id == id; }); assert(extension && extension.optionsPage);
diff --git a/chrome/browser/resources/md_extensions/shortcut_input.js b/chrome/browser/resources/md_extensions/shortcut_input.js index aeb278d..f2a834ec 100644 --- a/chrome/browser/resources/md_extensions/shortcut_input.js +++ b/chrome/browser/resources/md_extensions/shortcut_input.js
@@ -6,7 +6,7 @@ 'use strict'; // The UI to display and manage keyboard shortcuts set for extension commands. - var ShortcutInput = Polymer({ + const ShortcutInput = Polymer({ is: 'extensions-shortcut-input', behaviors: [I18nBehavior], @@ -37,7 +37,7 @@ }, ready: function() { - var node = this.$['input']; + const node = this.$['input']; node.addEventListener('mouseup', this.startCapture_.bind(this)); node.addEventListener('blur', this.endCapture_.bind(this)); node.addEventListener('focus', this.startCapture_.bind(this));
diff --git a/chrome/browser/resources/md_extensions/sidebar.js b/chrome/browser/resources/md_extensions/sidebar.js index ad6b4011..ee7978e7 100644 --- a/chrome/browser/resources/md_extensions/sidebar.js +++ b/chrome/browser/resources/md_extensions/sidebar.js
@@ -13,7 +13,7 @@ cr.define('extensions', function() { /** @interface */ - var SidebarListDelegate = function() {}; + const SidebarListDelegate = function() {}; SidebarListDelegate.prototype = { /** @@ -26,7 +26,7 @@ showKeyboardShortcuts: assertNotReached, }; - var Sidebar = Polymer({ + const Sidebar = Polymer({ is: 'extensions-sidebar', behaviors: [I18nBehavior],
diff --git a/chrome/browser/resources/md_extensions/toolbar.js b/chrome/browser/resources/md_extensions/toolbar.js index 6cb1226..f7e5051 100644 --- a/chrome/browser/resources/md_extensions/toolbar.js +++ b/chrome/browser/resources/md_extensions/toolbar.js
@@ -6,7 +6,7 @@ cr.define('extensions', function() { /** @interface */ - var ToolbarDelegate = function() {}; + const ToolbarDelegate = function() {}; ToolbarDelegate.prototype = { /** @@ -22,7 +22,7 @@ updateAllExtensions: assertNotReached, }; - var Toolbar = Polymer({ + const Toolbar = Polymer({ is: 'extensions-toolbar', behaviors: [I18nBehavior],
diff --git a/chrome/browser/resources/settings/site_settings/site_details.html b/chrome/browser/resources/settings/site_settings/site_details.html index 950b304d..1b3cb3a 100644 --- a/chrome/browser/resources/settings/site_settings/site_details.html +++ b/chrome/browser/resources/settings/site_settings/site_details.html
@@ -23,10 +23,12 @@ -webkit-padding-end: 0; } - /* When the 'Usage' section is omitted, all headings are removed. This - * reduces the start padding allowed for lists without headings. */ + /* When 'Usage' is omitted, subheadings are removed. Reduce the start + * padding allowed for lists without headings and add back vertical space + * that would normally be provided by the subheading. */ .list-frame.without-heading { -webkit-padding-start: var(--settings-box-row-padding); + margin-top: 12px; } #clearAndReset {
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc index 91795f9..01e155a 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc +++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -122,31 +122,21 @@ return false; } - bool allowed_incognito = - base::GetFieldTrialParamByFeatureAsBool(feature, "incognito", false); - if (IsIncognito() && !allowed_incognito) { + // Protected password entry pinging is enabled for all users. + if (feature.name == kProtectedPasswordEntryPinging.name) + return true; + + // Password field on focus pinging is enabled for !incognito && + // extended_reporting. + if (IsIncognito()) { *reason = DISABLED_DUE_TO_INCOGNITO; return false; } - - bool allowed_all_population = - base::GetFieldTrialParamByFeatureAsBool(feature, "all_population", false); - if (!allowed_all_population) { - bool allowed_extended_reporting = base::GetFieldTrialParamByFeatureAsBool( - feature, "extended_reporting", false); - if (IsExtendedReporting() && allowed_extended_reporting) - return true; // Ping enabled because this user opted in extended - // reporting. - - bool allowed_history_sync = - base::GetFieldTrialParamByFeatureAsBool(feature, "history_sync", false); - if (IsHistorySyncEnabled() && allowed_history_sync) - return true; - + if (!IsExtendedReporting()) { *reason = DISABLED_DUE_TO_USER_POPULATION; + return false; } - - return allowed_all_population; + return true; } bool ChromePasswordProtectionService::IsHistorySyncEnabled() {
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.h b/chrome/browser/safe_browsing/chrome_password_protection_service.h index 2749549..d954a04 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service.h +++ b/chrome/browser/safe_browsing/chrome_password_protection_service.h
@@ -62,17 +62,10 @@ void UpdateSecurityState(SBThreatType threat_type, content::WebContents* web_contents) override; - FRIEND_TEST_ALL_PREFIXES( - ChromePasswordProtectionServiceTest, - VerifyFinchControlForLowReputationPingSBEROnlyNoIncognito); - FRIEND_TEST_ALL_PREFIXES( - ChromePasswordProtectionServiceTest, - VerifyFinchControlForLowReputationPingSBERAndHistorySyncNoIncognito); FRIEND_TEST_ALL_PREFIXES(ChromePasswordProtectionServiceTest, - VerifyFinchControlForLowReputationPingAll); - FRIEND_TEST_ALL_PREFIXES( - ChromePasswordProtectionServiceTest, - VerifyFinchControlForLowReputationPingAllButNoIncognito); + VerifyUserPopulationForPasswordOnFocusPing); + FRIEND_TEST_ALL_PREFIXES(ChromePasswordProtectionServiceTest, + VerifyUserPopulationForProtectedPasswordEntryPing); FRIEND_TEST_ALL_PREFIXES(ChromePasswordProtectionServiceTest, VerifyGetSyncAccountType); FRIEND_TEST_ALL_PREFIXES(ChromePasswordProtectionServiceTest,
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc index 585e988c..f669e21d7 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc +++ b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
@@ -78,20 +78,15 @@ content_setting_map, ui_manager), is_incognito_(false), - is_extended_reporting_(false), - is_history_sync_enabled_(false) {} + is_extended_reporting_(false) {} bool IsExtendedReporting() override { return is_extended_reporting_; } bool IsIncognito() override { return is_incognito_; } - bool IsHistorySyncEnabled() override { return is_history_sync_enabled_; } // Configures the results returned by IsExtendedReporting(), IsIncognito(), // and IsHistorySyncEnabled(). - void ConfigService(bool is_incognito, - bool is_extended_reporting, - bool is_history_sync_enabled) { + void ConfigService(bool is_incognito, bool is_extended_reporting) { is_incognito_ = is_incognito; is_extended_reporting_ = is_extended_reporting; - is_history_sync_enabled_ = is_history_sync_enabled; } void SetUIManager(scoped_refptr<SafeBrowsingUIManager> ui_manager) { @@ -108,7 +103,6 @@ private: bool is_incognito_; bool is_extended_reporting_; - bool is_history_sync_enabled_; }; class ChromePasswordProtectionServiceTest @@ -152,28 +146,6 @@ return builder.Build().release(); } - // Sets up Finch trial feature parameters. - void SetFeatureParams(const base::Feature& feature, - const std::string& trial_name, - const Parameters& params) { - static std::set<std::string> features = {feature.name}; - params_manager_.ClearAllVariationParams(); - params_manager_.SetVariationParamsWithFeatureAssociations(trial_name, - params, features); - } - - // Creates Finch trial parameters. - Parameters CreateParameters(bool allowed_for_incognito, - bool allowed_for_all, - bool allowed_for_extended_reporting, - bool allowed_for_history_sync) { - return {{"incognito", allowed_for_incognito ? "true" : "false"}, - {"all_population", allowed_for_all ? "true" : "false"}, - {"extended_reporting", - allowed_for_extended_reporting ? "true" : "false"}, - {"history_sync", allowed_for_history_sync ? "true" : "false"}}; - } - void InitializeRequest(LoginReputationClientRequest::TriggerType type) { request_ = new PasswordProtectionRequest(web_contents(), GURL(kPhishingURL), GURL(), GURL(), std::string(), @@ -205,7 +177,6 @@ } protected: - variations::testing::VariationParamsManager params_manager_; base::test::ScopedFeatureList scoped_feature_list_; sync_preferences::TestingPrefServiceSyncable test_pref_service_; scoped_refptr<HostContentSettingsMap> content_setting_map_; @@ -215,225 +186,47 @@ }; TEST_F(ChromePasswordProtectionServiceTest, - VerifyFinchControlForLowReputationPingSBEROnlyNoIncognito) { + VerifyUserPopulationForPasswordOnFocusPing) { + // Password field on focus pinging is enabled on !incognito && SBER. + PasswordProtectionService::RequestOutcome reason; - - // By default kPasswordFieldOnFocusPinging feature is disabled. - EXPECT_FALSE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_FEATURE_DISABLED, - reason); - - // Enables kPasswordFieldOnFocusPinging feature. - scoped_feature_list_.InitAndEnableFeature(kPasswordFieldOnFocusPinging); - // Creates finch trial parameters correspond to the following experiment: - // "name": "SBEROnlyNoIncognito", - // "params": { - // "incognito": "false", - // "extended_reporting": "true", - // "history_sync": "false" - // }, - // "enable_features": [ - // "PasswordFieldOnFocusPinging" - // ] - Parameters sber_and_no_incognito = - CreateParameters(false, false, true, false); - SetFeatureParams(kPasswordFieldOnFocusPinging, "SBEROnlyNoIncognito", - sber_and_no_incognito); - - service_->ConfigService(false /*incognito*/, false /*SBER*/, false /*sync*/); + service_->ConfigService(false /*incognito*/, false /*SBER*/); EXPECT_FALSE( service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_USER_POPULATION, reason); - service_->ConfigService(false /*incognito*/, false /*SBER*/, true /*sync*/); - EXPECT_FALSE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_USER_POPULATION, reason); - - service_->ConfigService(false /*incognito*/, true /*SBER*/, false /*sync*/); + service_->ConfigService(false /*incognito*/, true /*SBER*/); EXPECT_TRUE( service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - service_->ConfigService(false /*incognito*/, true /*SBER*/, true /*sync*/); - EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - - service_->ConfigService(true /*incognito*/, false /*SBER*/, false /*sync*/); + service_->ConfigService(true /*incognito*/, false /*SBER*/); EXPECT_FALSE( service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_INCOGNITO, reason); - service_->ConfigService(true /*incognito*/, false /*SBER*/, true /*sync*/); - EXPECT_FALSE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_INCOGNITO, reason); - - service_->ConfigService(true /*incognito*/, true /*SBER*/, false /*sync*/); - EXPECT_FALSE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_INCOGNITO, reason); - - service_->ConfigService(true /*incognito*/, true /*SBER*/, true /*sync*/); + service_->ConfigService(true /*incognito*/, true /*SBER*/); EXPECT_FALSE( service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_INCOGNITO, reason); } TEST_F(ChromePasswordProtectionServiceTest, - VerifyFinchControlForLowReputationPingSBERAndHistorySyncNoIncognito) { + VerifyUserPopulationForProtectedPasswordEntryPing) { + // Protected password entry pinging is enabled for all safe browsing users. PasswordProtectionService::RequestOutcome reason; - // Enables kPasswordFieldOnFocusPinging feature. - scoped_feature_list_.InitAndEnableFeature(kPasswordFieldOnFocusPinging); - // Creates finch trial parameters correspond to the following experiment: - // "name": "SBERAndHistorySyncNoIncognito", - // "params": { - // "incognito": "false", - // "extended_reporting": "true", - // "history_sync": "true" - // }, - // "enable_features": [ - // "PasswordFieldOnFocusPinging" - // ] - Parameters sber_and_sync_no_incognito = - CreateParameters(false, false, true, true); - SetFeatureParams(kPasswordFieldOnFocusPinging, - "SBERAndHistorySyncNoIncognito", sber_and_sync_no_incognito); - service_->ConfigService(false /*incognito*/, false /*SBER*/, false /*sync*/); - EXPECT_FALSE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_USER_POPULATION, reason); - - service_->ConfigService(false /*incognito*/, false /*SBER*/, true /*sync*/); + service_->ConfigService(false /*incognito*/, false /*SBER*/); EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - - service_->ConfigService(false /*incognito*/, true /*SBER*/, false /*sync*/); + service_->IsPingingEnabled(kProtectedPasswordEntryPinging, &reason)); + service_->ConfigService(false /*incognito*/, true /*SBER*/); EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - - service_->ConfigService(false /*incognito*/, true /*SBER*/, true /*sync*/); + service_->IsPingingEnabled(kProtectedPasswordEntryPinging, &reason)); + service_->ConfigService(true /*incognito*/, false /*SBER*/); EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - - service_->ConfigService(true /*incognito*/, false /*SBER*/, false /*sync*/); - EXPECT_FALSE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_INCOGNITO, reason); - - service_->ConfigService(true /*incognito*/, false /*SBER*/, true /*sync*/); - EXPECT_FALSE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_INCOGNITO, reason); - - service_->ConfigService(true /*incognito*/, true /*SBER*/, false /*sync*/); - EXPECT_FALSE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_INCOGNITO, reason); - - service_->ConfigService(true /*incognito*/, true /*SBER*/, true /*sync*/); - EXPECT_FALSE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_INCOGNITO, reason); -} - -TEST_F(ChromePasswordProtectionServiceTest, - VerifyFinchControlForLowReputationPingAllButNoIncognito) { - PasswordProtectionService::RequestOutcome reason; - - // Enables kPasswordFieldOnFocusPinging feature. - scoped_feature_list_.InitAndEnableFeature(kPasswordFieldOnFocusPinging); - // Creates finch trial parameters correspond to the following experiment: - // "name": "AllButNoIncognito", - // "params": { - // "all_population": "true", - // "incongito": "false" - // }, - // "enable_features": [ - // "PasswordFieldOnFocusPinging" - // ] - Parameters all_users = CreateParameters(false, true, true, true); - SetFeatureParams(kPasswordFieldOnFocusPinging, "AllButNoIncognito", - all_users); - service_->ConfigService(false /*incognito*/, false /*SBER*/, false /*sync*/); + service_->IsPingingEnabled(kProtectedPasswordEntryPinging, &reason)); + service_->ConfigService(true /*incognito*/, true /*SBER*/); EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - - service_->ConfigService(false /*incognito*/, false /*SBER*/, true /*sync*/); - EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - - service_->ConfigService(false /*incognito*/, true /*SBER*/, false /*sync*/); - EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - - service_->ConfigService(false /*incognito*/, true /*SBER*/, true /*sync*/); - EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - - service_->ConfigService(true /*incognito*/, false /*SBER*/, false /*sync*/); - EXPECT_FALSE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_INCOGNITO, reason); - - service_->ConfigService(true /*incognito*/, false /*SBER*/, true /*sync*/); - EXPECT_FALSE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_INCOGNITO, reason); - - service_->ConfigService(true /*incognito*/, true /*SBER*/, false /*sync*/); - EXPECT_FALSE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_INCOGNITO, reason); - - service_->ConfigService(true /*incognito*/, true /*SBER*/, true /*sync*/); - EXPECT_FALSE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - EXPECT_EQ(PasswordProtectionService::DISABLED_DUE_TO_INCOGNITO, reason); -} - -TEST_F(ChromePasswordProtectionServiceTest, - VerifyFinchControlForLowReputationPingAll) { - PasswordProtectionService::RequestOutcome reason; - - // Enables kPasswordFieldOnFocusPinging feature. - scoped_feature_list_.InitAndEnableFeature(kPasswordFieldOnFocusPinging); - // Creates finch trial parameters correspond to the following experiment: - // "name": "All", - // "params": { - // "all_population": "true", - // "incognito": "true" - // }, - // "enable_features": [ - // "PasswordFieldOnFocusPinging" - // ] - Parameters all_users = CreateParameters(true, true, true, true); - SetFeatureParams(kPasswordFieldOnFocusPinging, "All", all_users); - service_->ConfigService(false /*incognito*/, false /*SBER*/, false /*sync*/); - EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - service_->ConfigService(false /*incognito*/, false /*SBER*/, true /*sync*/); - EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - service_->ConfigService(false /*incognito*/, true /*SBER*/, false /*sync*/); - EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - service_->ConfigService(false /*incognito*/, true /*SBER*/, true /*sync*/); - EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - service_->ConfigService(true /*incognito*/, false /*SBER*/, false /*sync*/); - EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - service_->ConfigService(true /*incognito*/, false /*SBER*/, true /*sync*/); - EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - service_->ConfigService(true /*incognito*/, true /*SBER*/, false /*sync*/); - EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); - service_->ConfigService(true /*incognito*/, true /*SBER*/, true /*sync*/); - EXPECT_TRUE( - service_->IsPingingEnabled(kPasswordFieldOnFocusPinging, &reason)); + service_->IsPingingEnabled(kProtectedPasswordEntryPinging, &reason)); } TEST_F(ChromePasswordProtectionServiceTest,
diff --git a/chrome/browser/search_engines/template_url_service_android.cc b/chrome/browser/search_engines/template_url_service_android.cc index ae9d8c3..47112066 100644 --- a/chrome/browser/search_engines/template_url_service_android.cc +++ b/chrome/browser/search_engines/template_url_service_android.cc
@@ -349,7 +349,7 @@ base::android::ConvertJavaStringToUTF16(env, jkeyword); data.SetShortName(keyword); data.SetKeyword(keyword); - data.SetURL("http://testurl"); + data.SetURL("https://testurl.com/?searchstuff={searchTerms}"); data.favicon_url = GURL("http://favicon.url"); data.safe_for_autoreplace = true; data.input_encodings.push_back("UTF-8"); @@ -362,6 +362,7 @@ base::Time::Now() - base::TimeDelta::FromDays((int) age_in_days); TemplateURL* t_url = template_url_service_->Add(base::MakeUnique<TemplateURL>(data)); + CHECK(t_url) << "Failed adding template url for: " << keyword; return base::android::ConvertUTF16ToJavaString(env, t_url->data().keyword()); }
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter_browser_tests.cc b/chrome/browser/ssl/chrome_expect_ct_reporter_browser_tests.cc index 657cd3e1..9680db7f 100644 --- a/chrome/browser/ssl/chrome_expect_ct_reporter_browser_tests.cc +++ b/chrome/browser/ssl/chrome_expect_ct_reporter_browser_tests.cc
@@ -33,6 +33,16 @@ void TearDown() override { run_loop_.reset(nullptr); } + std::unique_ptr<net::test_server::HttpResponse> ExpectCTHeaderRequestHandler( + const net::test_server::HttpRequest& request) { + std::unique_ptr<net::test_server::BasicHttpResponse> http_response( + new net::test_server::BasicHttpResponse()); + http_response->set_code(net::HTTP_OK); + http_response->AddCustomHeader( + "Expect-CT", "max-age=100, report-uri=" + report_uri_.spec()); + return http_response; + } + std::unique_ptr<net::test_server::HttpResponse> ReportRequestHandler( const net::test_server::HttpRequest& request) { EXPECT_TRUE(request.method == net::test_server::METHOD_POST || @@ -67,8 +77,15 @@ protected: void WaitForReport() { run_loop_->Run(); } + // Set the report-uri value to be used in the Expect-CT header for requests + // handled by ExpectCTHeaderRequestHandler. + void set_report_uri(const GURL& report_uri) { report_uri_ = report_uri; } + private: std::unique_ptr<base::RunLoop> run_loop_; + // The report-uri value to use in the Expect-CT header for requests handled by + // ExpectCTHeaderRequestHandler. + GURL report_uri_; DISALLOW_COPY_AND_ASSIGN(ExpectCTBrowserTest); }; @@ -129,4 +146,47 @@ // here. } +// Tests that Expect-CT HTTP headers are processed correctly. +IN_PROC_BROWSER_TEST_F(ExpectCTBrowserTest, + TestDynamicExpectCTHeaderProcessing) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + {features::kExpectCTReporting, + net::TransportSecurityState::kDynamicExpectCTFeature}, + {}); + + net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS); + test_server.RegisterRequestHandler( + base::Bind(&ExpectCTBrowserTest::ExpectCTHeaderRequestHandler, + base::Unretained(this))); + ASSERT_TRUE(test_server.Start()); + + net::EmbeddedTestServer report_server; + report_server.RegisterRequestHandler(base::Bind( + &ExpectCTBrowserTest::ReportRequestHandler, base::Unretained(this))); + ASSERT_TRUE(report_server.Start()); + + // Set up ExpectCTRequestHandler() to set Expect-CT headers that report to + // |report_server|. + set_report_uri(report_server.GetURL("/")); + + // Set up the mock cert verifier to accept |test_server|'s certificate as + // valid and as if it is issued by a known root. (CT checks are skipped for + // private roots.) + scoped_refptr<net::X509Certificate> cert(test_server.GetCertificate()); + net::CertVerifyResult verify_result; + verify_result.is_issued_by_known_root = true; + verify_result.verified_cert = cert; + verify_result.cert_status = 0; + mock_cert_verifier()->AddResultForCert(cert, verify_result, net::OK); + + // Navigate to a test server URL, whose header should trigger an Expect-CT + // report because the test server doesn't serve SCTs. + ui_test_utils::NavigateToURL(browser(), test_server.GetURL("/")); + WaitForReport(); + // WaitForReport() does not return util ReportRequestHandler runs, and the + // handler does all the assertions, so there are no more assertions needed + // here. +} + } // namespace
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc index eeaa6ae..d2a5991 100644 --- a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc +++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc
@@ -288,5 +288,12 @@ TestDidFinishNavigation(false, false, kCatCardTitle, "", 0UL); } +// Escaping a query with a special character. +TEST_F(AnswerCardSearchProviderTest, QueryEscaping) { + EXPECT_CALL(*contents(), + LoadURL(GURL("http://beasts.org/search?q=cat%26dog"))); + provider()->Start(false, base::UTF8ToUTF16("cat&dog")); +} + } // namespace test } // namespace app_list
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc index 5cfba50..c75abe70 100644 --- a/chrome/browser/ui/ash/chrome_screenshot_grabber.cc +++ b/chrome/browser/ui/ash/chrome_screenshot_grabber.cc
@@ -6,6 +6,9 @@ #include <stddef.h> +#include <string> +#include <vector> + #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/system_notifier.h" @@ -296,12 +299,8 @@ } // namespace ChromeScreenshotGrabber::ChromeScreenshotGrabber() - : screenshot_grabber_(new ui::ScreenshotGrabber( - this, - base::CreateTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}))), - profile_for_test_(NULL), + : screenshot_grabber_(new ui::ScreenshotGrabber(this)), + profile_for_test_(nullptr), weak_factory_(this) { screenshot_grabber_->AddObserver(this); } @@ -400,7 +399,6 @@ void ChromeScreenshotGrabber::PrepareFileAndRunOnBlockingPool( const base::FilePath& path, - scoped_refptr<base::TaskRunner> blocking_task_runner, const FileCallback& callback) { Profile* profile = ProfileManager::GetActiveUserProfile(); if (drive::util::IsUnderDriveMountPoint(path)) { @@ -409,8 +407,8 @@ base::Bind(&EnsureDirectoryExistsCallback, callback, profile, path)); return; } - ui::ScreenshotGrabberDelegate::PrepareFileAndRunOnBlockingPool( - path, blocking_task_runner, callback); + ui::ScreenshotGrabberDelegate::PrepareFileAndRunOnBlockingPool(path, + callback); } void ChromeScreenshotGrabber::OnScreenshotCompleted(
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber.h b/chrome/browser/ui/ash/chrome_screenshot_grabber.h index 223a43d..dabd9c8 100644 --- a/chrome/browser/ui/ash/chrome_screenshot_grabber.h +++ b/chrome/browser/ui/ash/chrome_screenshot_grabber.h
@@ -5,8 +5,11 @@ #ifndef CHROME_BROWSER_UI_ASH_CHROME_SCREENSHOT_GRABBER_H_ #define CHROME_BROWSER_UI_ASH_CHROME_SCREENSHOT_GRABBER_H_ +#include <memory> + #include "ash/screenshot_delegate.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "build/build_config.h" #include "chrome/browser/notifications/notification.h" #include "components/drive/chromeos/file_system_interface.h" @@ -41,7 +44,6 @@ // ui::ScreenshotGrabberDelegate: void PrepareFileAndRunOnBlockingPool( const base::FilePath& path, - scoped_refptr<base::TaskRunner> blocking_task_runner, const FileCallback& callback_on_blocking_pool) override; // ui::ScreenshotGrabberObserver:
diff --git a/chrome/browser/ui/cocoa/framed_browser_window.h b/chrome/browser/ui/cocoa/framed_browser_window.h index cdeb619..6acd269 100644 --- a/chrome/browser/ui/cocoa/framed_browser_window.h +++ b/chrome/browser/ui/cocoa/framed_browser_window.h
@@ -16,8 +16,8 @@ // Offsets from the top/left of the window frame to the top of the window // controls (zoom, close, miniaturize) for a window without a tabstrip. -const NSInteger kFramedWindowButtonsWithoutTabStripOffsetFromTop = 4; -const NSInteger kFramedWindowButtonsWithoutTabStripOffsetFromLeft = 8; +const NSInteger kFramedWindowButtonsWithoutTabStripOffsetFromTop = 3; +const NSInteger kFramedWindowButtonsWithoutTabStripOffsetFromLeft = 7; // Cocoa class representing a framed browser window. // We need to override NSWindow with our own class since we need access to all
diff --git a/chrome/browser/ui/cocoa/framed_browser_window.mm b/chrome/browser/ui/cocoa/framed_browser_window.mm index 692d811..acd5343 100644 --- a/chrome/browser/ui/cocoa/framed_browser_window.mm +++ b/chrome/browser/ui/cocoa/framed_browser_window.mm
@@ -163,7 +163,7 @@ // highlights the buttons on mouse enter event. That rect is added where // buttons used to be previously. [self forbidAddingWindowButtonsTrackingArea]; - } else { + } else if (hasTabStrip_) { // If Chrome does not use a full sized content view then AppKit adds the // window buttons to the root view, where they must be manually // re-positioned. @@ -197,6 +197,13 @@ [super dealloc]; } +- (NSUserInterfaceLayoutDirection)windowTitlebarLayoutDirection + NS_AVAILABLE_MAC(10_12) { + if (!cocoa_l10n_util::ShouldFlipWindowControlsInRTL()) + return NSUserInterfaceLayoutDirectionLeftToRight; + return [super windowTitlebarLayoutDirection]; +} + - (void)adjustTitlebarContainer:(NSView*)titlebarContainer { if ([self styleMask] & NSFullScreenWindowMask) return;
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc index c0a4755e..72e84d0 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -95,14 +95,6 @@ OobeUI::kAppLaunchSplashDisplay, OobeUI::kArcKioskSplashDisplay}; -OobeScreen kDimOverlayScreenIds[] = { - OobeScreen::SCREEN_CONFIRM_PASSWORD, - OobeScreen::SCREEN_GAIA_SIGNIN, - OobeScreen::SCREEN_OOBE_ENROLLMENT, - OobeScreen::SCREEN_PASSWORD_CHANGED, - OobeScreen::SCREEN_USER_IMAGE_PICKER -}; - const char kStringsJSPath[] = "strings.js"; const char kLockJSPath[] = "lock.js"; const char kLoginJSPath[] = "login.js"; @@ -374,11 +366,6 @@ OobeUI::~OobeUI() { network_dropdown_handler_->RemoveObserver(GetView<ErrorScreenHandler>()); - if (ash_util::IsRunningInMash()) { - // TODO: Ash needs to expose screen dimming api. See - // http://crbug.com/646034. - NOTIMPLEMENTED(); - } } CoreOobeView* OobeUI::GetCoreOobeView() { @@ -527,12 +514,6 @@ oobe_ui_md_mode_ = g_browser_process->local_state()->GetBoolean(prefs::kOobeMdMode); localized_strings->SetString("newOobeUI", oobe_ui_md_mode_ ? "on" : "off"); - - LoginDisplayHost* default_host = LoginDisplayHost::default_host(); - bool oobe_shield_hide = - default_host ? default_host->IsVoiceInteractionOobe() : false; - localized_strings->SetString("hideOobeShield", - oobe_shield_hide ? "on" : "off"); } void OobeUI::AddWebUIHandler(std::unique_ptr<BaseWebUIHandler> handler) { @@ -569,23 +550,6 @@ void OobeUI::CurrentScreenChanged(OobeScreen new_screen) { previous_screen_ = current_screen_; - const bool should_dim = - std::find(std::begin(kDimOverlayScreenIds), - std::end(kDimOverlayScreenIds), - new_screen) != std::end(kDimOverlayScreenIds); - if (!ash_util::IsRunningInMash()) { - if (!screen_dimmer_) { - screen_dimmer_ = base::MakeUnique<ash::ScreenDimmer>( - ash::ScreenDimmer::Container::LOCK_SCREEN); - } - screen_dimmer_->set_at_bottom(true); - screen_dimmer_->SetDimming(should_dim); - } else { - // TODO: Ash needs to expose screen dimming api. See - // http://crbug.com/646034. - NOTIMPLEMENTED(); - } - current_screen_ = new_screen; for (Observer& observer : observer_list_) observer.OnCurrentScreenChanged(current_screen_, new_screen);
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h index 5259255..a779705 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h +++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
@@ -20,10 +20,6 @@ #include "chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h" #include "content/public/browser/web_ui_controller.h" -namespace ash { -class ScreenDimmer; -} - namespace base { class DictionaryValue; } // namespace base @@ -247,8 +243,6 @@ // Observer of CrosSettings watching the kRebootOnShutdown policy. std::unique_ptr<ShutdownPolicyHandler> shutdown_policy_handler_; - std::unique_ptr<ash::ScreenDimmer> screen_dimmer_; - std::unique_ptr<OobeDisplayChooser> oobe_display_chooser_; // Store the deferred JS calls before the screen handler instance is
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc index c6d0eda8..ee9978a 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -872,14 +872,11 @@ SkColorSetA(ash::login_constants::kDefaultBaseColor, ash::login_constants::kTranslucentColorDarkenAlpha), dark_muted_color); - SkColor background_color = - SkColorSetA(base_color, ash::login_constants::kTranslucentAlpha); SkColor scroll_color = SkColorSetA(base_color, ash::login_constants::kScrollTranslucentAlpha); CallJS("login.AccountPickerScreen.setOverlayColors", color_utils::SkColorToRgbaString(dark_muted_color), - color_utils::SkColorToRgbaString(scroll_color), - color_utils::SkColorToRgbaString(background_color)); + color_utils::SkColorToRgbaString(scroll_color)); } void SigninScreenHandler::Initialize() {
diff --git a/chrome/installer/zucchini/BUILD.gn b/chrome/installer/zucchini/BUILD.gn index 261a2b5d..7b669a0 100644 --- a/chrome/installer/zucchini/BUILD.gn +++ b/chrome/installer/zucchini/BUILD.gn
@@ -28,7 +28,11 @@ "io_utils.h", "label_manager.cc", "label_manager.h", + "patch_reader.cc", + "patch_reader.h", "patch_utils.h", + "patch_writer.cc", + "patch_writer.h", "rel32_finder.cc", "rel32_finder.h", "rel32_utils.cc", @@ -81,6 +85,7 @@ "image_utils_unittest.cc", "io_utils_unittest.cc", "label_manager_unittest.cc", + "patch_read_write_unittest.cc", "patch_utils_unittest.cc", "rel32_finder_unittest.cc", "rel32_utils_unittest.cc",
diff --git a/chrome/installer/zucchini/README.md b/chrome/installer/zucchini/README.md index fa433eb3..c277682 100644 --- a/chrome/installer/zucchini/README.md +++ b/chrome/installer/zucchini/README.md
@@ -1,6 +1,5 @@ -Basic Definitions for Patching ------------------------------- +## Basic Definitions for Patching **Binary**: Executable image and data. Binaries may persist in an archive (e.g., chrome.7z), and need to be periodically updated. Formats for binaries @@ -10,7 +9,7 @@ **Patching**: Sending a "new" file to clients who have an "old" file by computing and transmitting a "patch" that can be used to transform "old" into -"new". Patches are compressed for transmission. A key performance metric is +"new". Patches are compressed for transmission. A key performance metric is patch size, which refers to the size of compressed patch file. For our experiments we use 7z. @@ -20,7 +19,7 @@ the expense is not too critical. **Patch application**: Transformation from "old" binaries to "new", using a -(downloaded) "patch". This is executed on client side on updates, so resource +(downloaded) "patch". This is executed on client side on updates, so resource constraints (e.g., time, RAM, disk space) is more stringent. Also, fault- tolerance is important. This is usually achieved by an update system by having a fallback method of directly downloading "new" in case of patching failure. @@ -29,6 +28,10 @@ **Local offset**: An offset relative to the start of a region of a file. +**Element**: A region in a file with associated executable type, represented by +the tuple (exe_type, offset, length). Every Element in new file is associated +with an Element in old file and patched independantly. + **Reference**: A directed connection between two offsets in a binary. For example, consider jump instructions in x86: @@ -102,6 +105,11 @@ "old" binary, at an offset of |src_offset|, that is similar to a region of "new" binary, at an offset of |dst_offset|. +**Raw delta unit**: Describes a raw modification to apply on the new image, as a +pair (copy_offset, diff), where copy_offset describes the position in new file +as an offset in the data that was copied from the old file, and diff is the +bytewise difference to apply. + **Associated Targets**: A target in "old" binary is associated with a target in "new" binary if both targets: 1. are part of similar regions from the same equivalence, and @@ -126,3 +134,116 @@ values that describe content on a higher level of abstraction, masking away undesirable noise in raw content. Notably, the projection encodes references based on their associated label. + +## Zucchini Ensemble Patch Format + +### Types + +**int8**: 8-bit unsigned int. + +**uint32**: 32-bit unsigned int, little-endian. + +**int32**: 32-bit signed int, little-endian. + +**Varints**: This is a generic variable-length encoding for integer quantities +that strips away leading (most-significant) null bytes. +The Varints format is borrowed from protocol-buffers, see +[documentation](https://developers.google.com/protocol-buffers/docs/encoding#varints) +for more info. + +**varuint32**: A uint32 encoded using Varints format. + +**varint32**: A int32 encoded using Varints format. + +### File Layout + +Name | Format | Description +--- | --- | --- +header | PatchHeader | The header. +patch_type | uint32 | Type of this patch, see `enum PatchType`. +elements_count | uint32 | Number of patch units. +elements | PatchElement[elements_count] | List of all patch elements. + +Position of elements in new file is ascending. + +### Structures + +**PatchHeader** + +Name | Format | Description +--- | --- | --- +magic | uint32 = kMagic | Magic value. +old_size | uint32 | Size of old file in bytes. +old_crc | uint32 | CRC32 of old file. +new_size | uint32 | Size of new file in bytes. +new_crc | uint32 | CRC32 of new file. + +**kMagic** == `'Z' | ('u' << 8) | ('c' << 16)` + +**PatchElement** +Contains all the information required to produce a single element in new file. + +Name | Format | Description +--- | --- | --- +header | PatchElementHeader | The header. +equivalences | EquivalenceList | List of equivalences. +raw_deltas | RawDeltaList | List of raw deltas. +reference_deltas | ReferenceDeltaList | List of reference deltas. +pool_count | uint32 | Number of pools. +extra_targets | ExtraTargetList[pool_count] | Lists of extra targets. + +**PatchElementHeader** +Describes a correspondence between an element in old and in new files. Some +redundancy arise from storing |new_offset|, but it is necessary to make +PatchElement self contained. + +Name | Format | Description +--- | --- | --- +old_offset | uint32 | Starting offset of the element in old file. +new_offset | uint32 | Starting offset of the element in new file. +old_length | uint32 | Length of the element in old file. +new_length | uint32 | Length of the element in new file. +exe_type | uint32 | Executable type for this unit, see `enum ExecutableType`. + +**EquivalenceList** +Encodes a list of equivalences, where dst offsets (in new image) are ascending. + +Name | Format | Description +--- | --- | --- +src_skip | Buffer<varint32> | Src offset for each equivalence, delta encoded. +dst_skip | Buffer<varuint32> | Dst offset for each equivalence, delta encoded. +copy_count | Buffer<varuint32> | Length for each equivalence. + +**RawDeltaList** +Encodes a list of raw delta units, with ascending copy offsets. + +Name | Format | Description +--- | --- | --- +raw_delta_skip | Buffer<varuint32> | Copy offset for each delta unit, delta encoded and biased by -1. +raw_delta_diff | Buffer<int8> | Bytewise difference for each delta unit. + +**ReferenceDeltaList** +Encodes a list of reference deltas, in the order they appear in the new +image file. A reference delta is a signed integer representing a jump through a +list of targets. + +Name | Format | Description +--- | --- | --- +reference_delta | Buffer<varuint32> | Vector of reference deltas. + +**ExtraTargetList** +Encodes a list of additional targets in the new image file, in ascending +order. + +Name | Format | Description +--- | --- | --- +pool_tag | uint8_t | Unique identifier for this pool of targets. +extra_targets | Buffer<varuint32> | Additional targets, delta encoded and biased by -1. + +**Buffer<T>** +A generic vector of data. + +Name | Format | Description +--- | --- | --- +size |uint32 | Size of content in bytes. +content |T[] | List of integers.
diff --git a/chrome/installer/zucchini/image_utils.h b/chrome/installer/zucchini/image_utils.h index 956fbb2..dfb55bd1 100644 --- a/chrome/installer/zucchini/image_utils.h +++ b/chrome/installer/zucchini/image_utils.h
@@ -126,19 +126,33 @@ kExeTypeElfArm32 = 4, kExeTypeElfAArch64 = 5, kExeTypeDex = 6, + kNumExeType }; -// Descibes where to find an executable embedded in an image. +// Descibes a region in an image with associated executable type. Note that +// |exe_type| can be kExeTypeNoOp, in which case the Element descibes a region +// of raw data. struct Element { ExecutableType exe_type; offset_t offset; offset_t length; + + // Returns the end offset of this element. + offset_t EndOffset() const { return offset + length; } + + // Returns true if the element fits in an image of size |total_size|, false + // otherwise. + bool FitsIn(offset_t total_size) const { + return offset <= total_size && total_size - offset >= length; + } }; // A matched pair of Elements. struct ElementMatch { Element old_element; Element new_element; + + bool IsValid() const { return old_element.exe_type == new_element.exe_type; } }; } // namespace zucchini
diff --git a/chrome/installer/zucchini/patch_read_write_unittest.cc b/chrome/installer/zucchini/patch_read_write_unittest.cc new file mode 100644 index 0000000..0e0d8496 --- /dev/null +++ b/chrome/installer/zucchini/patch_read_write_unittest.cc
@@ -0,0 +1,604 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/installer/zucchini/patch_reader.h" +#include "chrome/installer/zucchini/patch_writer.h" + +#include <stddef.h> +#include <stdint.h> + +#include <utility> +#include <vector> + +#include "testing/gtest/include/gtest/gtest.h" + +namespace zucchini { + +namespace { + +// Used for initialization of raw test data. +using ByteVector = std::vector<uint8_t>; + +// Helper function that creates an object of type |T| and intializes it from +// data in |buffer|. Ensures initialization is successful. |buffer| is passed as +// pointer to avoid passing a temporay, which can causes dangling references. +template <class T> +T TestInitialize(const ByteVector* buffer) { + T value; + BufferSource buffer_source(buffer->data(), buffer->size()); + EXPECT_TRUE(value.Initialize(&buffer_source)); + EXPECT_TRUE(buffer_source.empty()); // Make sure all data has been consumed + return value; +} + +// Helper function that creates an object of type |T| and tries to intialize it +// from invalid data in |buffer|, expecting the operation to fail. |buffer| is +// passed as pointer to avoid passing a temporary, which can causes dangling +// references. +template <class T> +void TestInvalidInitialize(const ByteVector* buffer) { + T value; + BufferSource buffer_source(buffer->data(), buffer->size()); + EXPECT_FALSE(value.Initialize(&buffer_source)); +} + +// Helper function that serializes |value| into a buffer. Ensures that +// serialization is successful and that the result matches |expected|. +template <class T> +void TestSerialize(const ByteVector& expected, const T& value) { + size_t size = value.SerializedSize(); + EXPECT_EQ(expected.size(), size); + ByteVector buffer(size); + BufferSink buffer_sink(buffer.data(), buffer.size()); + EXPECT_TRUE(value.SerializeInto(&buffer_sink)); + EXPECT_EQ(expected, buffer); +} + +} // namespace + +bool operator==(const ByteVector& a, ConstBufferView b) { + return a == ByteVector(b.begin(), b.end()); +} + +TEST(PatchTest, ParseSerializeElementMatch) { + ByteVector data = { + 1, 0, 0, 0, // old_offset + 3, 0, 0, 0, // new_offset + 2, 0, 0, 0, // old_length + 4, 0, 0, 0, // new_length + 6, 0, 0, 0, // kExeTypeDex + }; + BufferSource buffer_source(data.data(), data.size()); + ElementMatch element_match = {}; + EXPECT_TRUE(patch::ParseElementMatch(&buffer_source, &element_match)); + + EXPECT_EQ(kExeTypeDex, element_match.old_element.exe_type); + EXPECT_EQ(kExeTypeDex, element_match.new_element.exe_type); + EXPECT_EQ(size_t(1), element_match.old_element.offset); + EXPECT_EQ(size_t(2), element_match.old_element.length); + EXPECT_EQ(size_t(3), element_match.new_element.offset); + EXPECT_EQ(size_t(4), element_match.new_element.length); + + size_t size = patch::SerializedElementMatchSize(element_match); + EXPECT_EQ(data.size(), size); + ByteVector buffer(size); + BufferSink buffer_sink(buffer.data(), buffer.size()); + EXPECT_TRUE(patch::SerializeElementMatch(element_match, &buffer_sink)); + EXPECT_EQ(data, buffer); +} + +TEST(PatchTest, ParseElementMatchTooSmall) { + ByteVector data = {4}; + BufferSource buffer_source(data.data(), data.size()); + ElementMatch element_match = {}; + EXPECT_FALSE(patch::ParseElementMatch(&buffer_source, &element_match)); +} + +TEST(PatchTest, ParseSerializeElementMatchExeMismatch) { + ByteVector buffer(28); + BufferSink buffer_sink(buffer.data(), buffer.size()); + EXPECT_FALSE(patch::SerializeElementMatch( + ElementMatch{{kExeTypeNoOp, 1, 2}, {kExeTypeWin32X86, 3, 4}}, + &buffer_sink)); +} + +TEST(PatchTest, SerializeElementMatchTooSmall) { + ByteVector buffer(4); + BufferSink buffer_sink(buffer.data(), buffer.size()); + EXPECT_FALSE(patch::SerializeElementMatch( + ElementMatch{{kExeTypeDex, 1, 2}, {kExeTypeDex, 3, 4}}, &buffer_sink)); +} + +TEST(PatchTest, ParseSerializeBuffer) { + auto TestSerialize = [](const ByteVector& expected, const ByteVector& value) { + size_t size = patch::SerializedBufferSize(value); + EXPECT_EQ(expected.size(), size); + ByteVector buffer(size); + BufferSink buffer_sink(buffer.data(), buffer.size()); + EXPECT_TRUE(patch::SerializeBuffer(value, &buffer_sink)); + EXPECT_EQ(expected, buffer); + }; + + // |data| is passed as pointer to avoid passing a temporay, which can causes + // dangling references. + auto TestParse = [](const ByteVector* data) { + BufferSource value; + BufferSource buffer_source(data->data(), data->size()); + EXPECT_TRUE(patch::ParseBuffer(&buffer_source, &value)); + // Make sure all data has been consumed. + EXPECT_TRUE(buffer_source.empty()); + return value; + }; + + ByteVector data = { + 0, 0, 0, 0, // size + }; + BufferSource buffer = TestParse(&data); + EXPECT_TRUE(buffer.empty()); + TestSerialize(data, ByteVector({})); + + data = { + 3, 0, 0, 0, // size + 1, 2, 3 // content + }; + buffer = TestParse(&data); + EXPECT_EQ(3U, buffer.size()); + EXPECT_EQ(ByteVector({1, 2, 3}), ByteVector(buffer.begin(), buffer.end())); + TestSerialize(data, ByteVector({1, 2, 3})); + + // Ill-formed input. + data = { + 3, 0, 0, 0, // size + 1, 2 // insufficient content + }; + BufferSource value; + BufferSource buffer_source(data.data(), data.size()); + EXPECT_FALSE(patch::ParseBuffer(&buffer_source, &value)); + EXPECT_TRUE(value.empty()); +} + +TEST(PatchTest, SerializeBufferTooSmall) { + ByteVector buffer(3); + BufferSink buffer_sink(buffer.data(), buffer.size()); + EXPECT_FALSE(patch::SerializeBuffer(ByteVector(), &buffer_sink)); +} + +TEST(EquivalenceSinkSourceTest, Empty) { + ByteVector data = { + 0, 0, 0, 0, // src_skip size + 0, 0, 0, 0, // dst_skip size + 0, 0, 0, 0, // copy_count size + }; + EquivalenceSource equivalence_source = + TestInitialize<EquivalenceSource>(&data); + + EXPECT_FALSE(equivalence_source.GetNext()); + EXPECT_TRUE(equivalence_source.Done()); + + TestSerialize(data, EquivalenceSink()); +} + +TEST(EquivalenceSourceSinkTest, Normal) { + ByteVector data = { + 2, 0, 0, 0, // src_skip size + 6, 7, // src_skip content + 2, 0, 0, 0, // dst_skip size + 7, 1, // dst_skip content + 2, 0, 0, 0, // copy_count size + 2, 1 // copy_count content + }; + EquivalenceSource equivalence_source = + TestInitialize<EquivalenceSource>(&data); + auto equivalence = equivalence_source.GetNext(); + EXPECT_FALSE(equivalence_source.Done()); + EXPECT_TRUE(equivalence.has_value()); + EXPECT_EQ(offset_t(3), equivalence->src_offset); + EXPECT_EQ(offset_t(7), equivalence->dst_offset); + EXPECT_EQ(offset_t(2), equivalence->length); + + equivalence = equivalence_source.GetNext(); + EXPECT_TRUE(equivalence_source.Done()); + EXPECT_TRUE(equivalence.has_value()); + EXPECT_EQ(offset_t(1), equivalence->src_offset); + EXPECT_EQ(offset_t(10), equivalence->dst_offset); + EXPECT_EQ(offset_t(1), equivalence->length); + + equivalence = equivalence_source.GetNext(); + EXPECT_FALSE(equivalence.has_value()); + + EquivalenceSink equivalence_sink; + equivalence_sink.PutNext(Equivalence{3, 7, 2}); + equivalence_sink.PutNext(Equivalence{1, 10, 1}); + TestSerialize(data, equivalence_sink); +} + +TEST(ExtraDataSourceSinkTest, Empty) { + ByteVector data = { + 0, 0, 0, 0, // extra_data size + }; + ExtraDataSource extra_data_source = TestInitialize<ExtraDataSource>(&data); + + EXPECT_FALSE(extra_data_source.GetNext(2)); + EXPECT_TRUE(extra_data_source.Done()); + + TestSerialize(data, ExtraDataSink()); +} + +TEST(ExtraDataSourceSinkTest, Normal) { + ByteVector data = { + 5, 0, 0, 0, // extra_data size + 1, 2, 3, 4, 5, // extra_data content + }; + ExtraDataSource extra_data_source = TestInitialize<ExtraDataSource>(&data); + EXPECT_FALSE(extra_data_source.Done()); + + auto extra_data = extra_data_source.GetNext(3); + EXPECT_FALSE(extra_data_source.Done()); + EXPECT_TRUE(extra_data.has_value()); + EXPECT_EQ(size_t(3), extra_data->size()); + EXPECT_EQ(ByteVector({1, 2, 3}), + ByteVector(extra_data->begin(), extra_data->end())); + + extra_data = extra_data_source.GetNext(2); + EXPECT_TRUE(extra_data_source.Done()); + EXPECT_TRUE(extra_data.has_value()); + EXPECT_EQ(ByteVector({4, 5}), + ByteVector(extra_data->begin(), extra_data->end())); + + extra_data = extra_data_source.GetNext(2); + EXPECT_FALSE(extra_data.has_value()); + + ExtraDataSink extra_data_sink; + + ByteVector content = {1, 2, 3}; + extra_data_sink.PutNext({content.data(), content.size()}); + content = {4, 5}; + extra_data_sink.PutNext({content.data(), content.size()}); + TestSerialize(data, extra_data_sink); +} + +TEST(RawDeltaSourceSinkTest, Empty) { + ByteVector data = { + 0, 0, 0, 0, // raw_delta_skip size + 0, 0, 0, 0, // raw_delta_diff size + }; + RawDeltaSource raw_delta_source = TestInitialize<RawDeltaSource>(&data); + + EXPECT_FALSE(raw_delta_source.GetNext()); + EXPECT_TRUE(raw_delta_source.Done()); + + TestSerialize(data, RawDeltaSink()); +} + +TEST(RawDeltaSinkSourceSinkTest, Normal) { + ByteVector data = { + 3, 0, 0, 0, // raw_delta_skip size + 1, 3, 0, // raw_delta_skip content + 3, 0, 0, 0, // raw_delta_diff size + 42, 24, 235, // raw_delta_diff content + }; + RawDeltaSource raw_delta_source = TestInitialize<RawDeltaSource>(&data); + EXPECT_FALSE(raw_delta_source.Done()); + + auto raw_delta = raw_delta_source.GetNext(); + EXPECT_FALSE(raw_delta_source.Done()); + EXPECT_TRUE(raw_delta.has_value()); + EXPECT_EQ(1U, raw_delta->copy_offset); + EXPECT_EQ(42, raw_delta->diff); + + raw_delta = raw_delta_source.GetNext(); + EXPECT_FALSE(raw_delta_source.Done()); + EXPECT_TRUE(raw_delta.has_value()); + EXPECT_EQ(5U, raw_delta->copy_offset); + EXPECT_EQ(24, raw_delta->diff); + + raw_delta = raw_delta_source.GetNext(); + EXPECT_TRUE(raw_delta_source.Done()); + EXPECT_TRUE(raw_delta.has_value()); + EXPECT_EQ(6U, raw_delta->copy_offset); + EXPECT_EQ(-21, raw_delta->diff); + + EXPECT_FALSE(raw_delta_source.GetNext()); + EXPECT_TRUE(raw_delta_source.Done()); + + RawDeltaSink raw_delta_sink; + raw_delta_sink.PutNext({1, 42}); + raw_delta_sink.PutNext({5, 24}); + raw_delta_sink.PutNext({6, -21}); + TestSerialize(data, raw_delta_sink); +} + +TEST(ReferenceDeltaSourceSinkTest, Empty) { + ByteVector data = { + 0, 0, 0, 0, // reference_delta size + }; + ReferenceDeltaSource reference_delta_source = + TestInitialize<ReferenceDeltaSource>(&data); + + EXPECT_FALSE(reference_delta_source.GetNext()); + EXPECT_TRUE(reference_delta_source.Done()); + + TestSerialize(data, ReferenceDeltaSink()); +} + +TEST(ReferenceDeltaSourceSinkTest, Normal) { + ByteVector data = { + 2, 0, 0, 0, // reference_delta size + 84, 47, // reference_delta content + }; + ReferenceDeltaSource reference_delta_source = + TestInitialize<ReferenceDeltaSource>(&data); + EXPECT_FALSE(reference_delta_source.Done()); + + auto delta = reference_delta_source.GetNext(); + EXPECT_FALSE(reference_delta_source.Done()); + EXPECT_TRUE(delta.has_value()); + EXPECT_EQ(42, *delta); + + delta = reference_delta_source.GetNext(); + EXPECT_TRUE(reference_delta_source.Done()); + EXPECT_TRUE(delta.has_value()); + EXPECT_EQ(-24, *delta); + + EXPECT_FALSE(reference_delta_source.GetNext()); + EXPECT_TRUE(reference_delta_source.Done()); + + ReferenceDeltaSink reference_delta; + reference_delta.PutNext(42); + reference_delta.PutNext(-24); + TestSerialize(data, reference_delta); +} + +TEST(TargetSourceSinkTest, Empty) { + ByteVector data = { + 0, 0, 0, 0, // extra_targets size + }; + TargetSource target_source = TestInitialize<TargetSource>(&data); + + EXPECT_FALSE(target_source.GetNext()); + EXPECT_TRUE(target_source.Done()); + + TestSerialize(data, TargetSink()); +} + +TEST(TargetSourceSinkTest, Normal) { + ByteVector data = { + 2, 0, 0, 0, // extra_targets size + 3, 1, // extra_targets content + }; + TargetSource target_source = TestInitialize<TargetSource>(&data); + EXPECT_FALSE(target_source.Done()); + + auto target = target_source.GetNext(); + EXPECT_FALSE(target_source.Done()); + EXPECT_TRUE(target.has_value()); + EXPECT_EQ(3U, *target); + + target = target_source.GetNext(); + EXPECT_TRUE(target_source.Done()); + EXPECT_TRUE(target.has_value()); + EXPECT_EQ(5U, *target); + + EXPECT_FALSE(target_source.GetNext()); + EXPECT_TRUE(target_source.Done()); + + TargetSink target_sink; + target_sink.PutNext(3); + target_sink.PutNext(5); + TestSerialize(data, target_sink); +} + +TEST(PatchElementTest, Normal) { + ByteVector data = { + 0x01, 0, 0, 0, // old_offset + 0x03, 0, 0, 0, // new_offset + 0x02, 0, 0, 0, // old_length + 0x04, 0, 0, 0, // new_length + 1, 0, 0, 0, // EXE_TYPE_WIN32_X86 + + 1, 0, 0, 0, // src_skip size + 0x10, // src_skip content + 1, 0, 0, 0, // dst_skip size + 0x11, // dst_skip content + 1, 0, 0, 0, // copy_count size + 0x12, // copy_count content + + 1, 0, 0, 0, // extra_data size + 0x13, // extra_data content + + 1, 0, 0, 0, // raw_delta_skip size + 0x14, // raw_delta_skip content + 1, 0, 0, 0, // raw_delta_diff size + 0x15, // raw_delta_diff content + + 1, 0, 0, 0, // reference_delta size + 0x16, // reference_delta content + + 2, 0, 0, 0, // pool count + 0, // pool_tag + 1, 0, 0, 0, // extra_targets size + 0x17, // extra_targets content + 2, // pool_tag + 1, 0, 0, 0, // extra_targets size + 0x18, // extra_targets content + }; + + PatchElementReader patch_element_reader = + TestInitialize<PatchElementReader>(&data); + + ElementMatch element_match = patch_element_reader.element_match(); + EXPECT_EQ(kExeTypeWin32X86, element_match.old_element.exe_type); + EXPECT_EQ(0x01U, element_match.old_element.offset); + EXPECT_EQ(0x02U, element_match.old_element.length); + EXPECT_EQ(kExeTypeWin32X86, element_match.new_element.exe_type); + EXPECT_EQ(0x03U, element_match.new_element.offset); + EXPECT_EQ(0x04U, element_match.new_element.length); + + EXPECT_EQ(3U, patch_element_reader.pool_count()); + + EquivalenceSource equivalence_source = + patch_element_reader.GetEquivalenceSource(); + EXPECT_EQ(ByteVector({0x10}), equivalence_source.src_skip()); + EXPECT_EQ(ByteVector({0x11}), equivalence_source.dst_skip()); + EXPECT_EQ(ByteVector({0x12}), equivalence_source.copy_count()); + + ExtraDataSource extra_data_source = patch_element_reader.GetExtraDataSource(); + EXPECT_EQ(ByteVector({0x13}), extra_data_source.extra_data()); + + RawDeltaSource raw_delta_source = patch_element_reader.GetRawDeltaSource(); + EXPECT_EQ(ByteVector({0x14}), raw_delta_source.raw_delta_skip()); + EXPECT_EQ(ByteVector({0x15}), raw_delta_source.raw_delta_diff()); + + ReferenceDeltaSource reference_delta_source = + patch_element_reader.GetReferenceDeltaSource(); + EXPECT_EQ(ByteVector({0x16}), reference_delta_source.reference_delta()); + + TargetSource target_source1 = + patch_element_reader.GetExtraTargetSource(PoolTag(0)); + EXPECT_EQ(ByteVector({0x17}), target_source1.extra_targets()); + TargetSource target_source2 = + patch_element_reader.GetExtraTargetSource(PoolTag(1)); + EXPECT_EQ(ByteVector({}), target_source2.extra_targets()); + TargetSource target_source3 = + patch_element_reader.GetExtraTargetSource(PoolTag(2)); + EXPECT_EQ(ByteVector({0x18}), target_source3.extra_targets()); + + PatchElementWriter patch_element_writer(element_match); + + patch_element_writer.SetEquivalenceSink( + EquivalenceSink({0x10}, {0x11}, {0x12})); + patch_element_writer.SetExtraDataSink(ExtraDataSink({0x13})); + patch_element_writer.SetRawDeltaSink(RawDeltaSink({0x14}, {0x15})); + patch_element_writer.SetReferenceDeltaSink(ReferenceDeltaSink({0x16})); + patch_element_writer.SetTargetSink(PoolTag(0), TargetSink({0x17})); + patch_element_writer.SetTargetSink(PoolTag(2), TargetSink({0x18})); + TestSerialize(data, patch_element_writer); +} + +TEST(EnsemblePatchTest, RawPatch) { + ByteVector data = { + 0x5A, 0x75, 0x63, 0x00, // magic + 0x10, 0x32, 0x54, 0x76, // old_size + 0x00, 0x11, 0x22, 0x33, // old_crc + 0x98, 0xBA, 0xDC, 0xFE, // new_size + 0x44, 0x55, 0x66, 0x77, // new_crc + + 0, 0, 0, 0, // kRawPatch + + 1, 0, 0, 0, // number of element + + 0x01, 0, 0, 0, // old_offset + 0x00, 0, 0, 0, // new_offset + 0x02, 0, 0, 0, // old_length + 0x98, 0xBA, 0xDC, 0xFE, // new_length + 1, 0, 0, 0, // EXE_TYPE_WIN32_X86 + 0, 0, 0, 0, // src_skip size + 0, 0, 0, 0, // dst_skip size + 0, 0, 0, 0, // copy_count size + 0, 0, 0, 0, // extra_data size + 0, 0, 0, 0, // raw_delta_skip size + 0, 0, 0, 0, // raw_delta_diff size + 0, 0, 0, 0, // reference_delta size + 0, 0, 0, 0, // pool count + }; + + EnsemblePatchReader ensemble_patch_reader = + TestInitialize<EnsemblePatchReader>(&data); + + PatchHeader header = ensemble_patch_reader.header(); + EXPECT_EQ(PatchHeader::kMagic, header.magic); + EXPECT_EQ(0x76543210U, header.old_size); + EXPECT_EQ(0x33221100U, header.old_crc); + EXPECT_EQ(0xFEDCBA98U, header.new_size); + EXPECT_EQ(0x77665544U, header.new_crc); + + EXPECT_EQ(PatchType::kRawPatch, ensemble_patch_reader.patch_type()); + + const std::vector<PatchElementReader>& elements = + ensemble_patch_reader.elements(); + EXPECT_EQ(size_t(1), elements.size()); + + EnsemblePatchWriter ensemble_patch_writer(header); + ensemble_patch_writer.SetPatchType(PatchType::kRawPatch); + PatchElementWriter patch_element_writer(elements[0].element_match()); + patch_element_writer.SetEquivalenceSink({}); + patch_element_writer.SetExtraDataSink({}); + patch_element_writer.SetRawDeltaSink({}); + patch_element_writer.SetReferenceDeltaSink({}); + ensemble_patch_writer.AddElement(std::move(patch_element_writer)); + + TestSerialize(data, ensemble_patch_writer); +} + +TEST(EnsemblePatchTest, CheckFile) { + ByteVector data = { + 0x5A, 0x75, 0x63, 0x00, // magic + 0x05, 0x00, 0x00, 0x00, // old_size + 0xDF, 0x13, 0xE4, 0x10, // old_crc + 0x03, 0x00, 0x00, 0x00, // new_size + 0xDC, 0xF7, 0x00, 0x40, // new_crc + 2, 0, 0, 0, // kEnsemblePatch + + 1, 0, 0, 0, // number of element + + 0x01, 0, 0, 0, // old_offset + 0x00, 0, 0, 0, // new_offset + 0x02, 0, 0, 0, // old_length + 0x03, 0, 0, 0, // new_length + 1, 0, 0, 0, // EXE_TYPE_WIN32_X86 + 0, 0, 0, 0, // src_skip size + 0, 0, 0, 0, // dst_skip size + 0, 0, 0, 0, // copy_count size + 0, 0, 0, 0, // extra_data size + 0, 0, 0, 0, // raw_delta_skip size + 0, 0, 0, 0, // raw_delta_diff size + 0, 0, 0, 0, // reference_delta size + 0, 0, 0, 0, // pool count + }; + + EnsemblePatchReader ensemble_patch_reader = + TestInitialize<EnsemblePatchReader>(&data); + + ByteVector old_file = {0x10, 0x32, 0x54, 0x76, 0x98}; + ByteVector new_file = {0xBA, 0xDC, 0xFE}; + + ConstBufferView old_image(old_file.data(), old_file.size()); + ConstBufferView new_image(new_file.data(), new_file.size()); + + EXPECT_TRUE(ensemble_patch_reader.CheckOldFile(old_image)); + EXPECT_TRUE(ensemble_patch_reader.CheckNewFile(new_image)); + EXPECT_FALSE(ensemble_patch_reader.CheckOldFile(new_image)); + EXPECT_FALSE(ensemble_patch_reader.CheckNewFile(old_image)); +} + +TEST(EnsemblePatchTest, InvalidMagic) { + ByteVector data = { + 0x42, 0x42, 0x42, 0x00, // magic + 0x10, 0x32, 0x54, 0x76, // old_size + 0x00, 0x11, 0x22, 0x33, // old_crc + 0x03, 0x00, 0x00, 0x00, // new_size + 0x44, 0x55, 0x66, 0x77, // new_crc + 0, 0, 0, 0, // kRawPatch + + 1, 0, 0, 0, // number of element + + 0x01, 0, 0, 0, // old_offset + 0x00, 0, 0, 0, // new_offset + 0x02, 0, 0, 0, // old_length + 0x03, 0, 0, 0, // new_length + 1, 0, 0, 0, // EXE_TYPE_WIN32_X86 + 0, 0, 0, 0, // src_skip size + 0, 0, 0, 0, // dst_skip size + 0, 0, 0, 0, // copy_count size + 0, 0, 0, 0, // extra_data size + 0, 0, 0, 0, // raw_delta_skip size + 0, 0, 0, 0, // raw_delta_diff size + 0, 0, 0, 0, // reference_delta size + 0, 0, 0, 0, // pool count + }; + + TestInvalidInitialize<EnsemblePatchReader>(&data); +} + +} // namespace zucchini
diff --git a/chrome/installer/zucchini/patch_reader.cc b/chrome/installer/zucchini/patch_reader.cc new file mode 100644 index 0000000..402076d --- /dev/null +++ b/chrome/installer/zucchini/patch_reader.cc
@@ -0,0 +1,341 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/installer/zucchini/patch_reader.h" + +#include <type_traits> +#include <utility> + +#include "base/numerics/safe_conversions.h" +#include "chrome/installer/zucchini/crc32.h" + +namespace zucchini { + +namespace patch { + +bool ParseElementMatch(BufferSource* source, ElementMatch* element_match) { + PatchElementHeader element_header; + if (!source->GetValue(&element_header)) { + LOG(ERROR) << "Impossible to read ElementMatch from source."; + LOG(ERROR) << base::debug::StackTrace().ToString(); + return false; + } + ExecutableType exe_type = + static_cast<ExecutableType>(element_header.exe_type); + if (exe_type >= kNumExeType) { + LOG(ERROR) << "Invalid ExecutableType encountered."; + LOG(ERROR) << base::debug::StackTrace().ToString(); + return false; + } + element_match->old_element.offset = element_header.old_offset; + element_match->new_element.offset = element_header.new_offset; + element_match->old_element.length = element_header.old_length; + element_match->new_element.length = element_header.new_length; + element_match->old_element.exe_type = exe_type; + element_match->new_element.exe_type = exe_type; + return true; +} + +bool ParseBuffer(BufferSource* source, BufferSource* buffer) { + uint32_t size = 0; + if (!source->GetValue(&size)) { + LOG(ERROR) << "Impossible to read buffer size from source."; + LOG(ERROR) << base::debug::StackTrace().ToString(); + return false; + } + if (!source->GetRegion(base::checked_cast<size_t>(size), buffer)) { + LOG(ERROR) << "Impossible to read buffer content from source."; + LOG(ERROR) << base::debug::StackTrace().ToString(); + return false; + } + return true; +} + +} // namespace patch + +/******** EquivalenceSource ********/ + +EquivalenceSource::EquivalenceSource() = default; +EquivalenceSource::EquivalenceSource(const EquivalenceSource&) = default; +EquivalenceSource::~EquivalenceSource() = default; + +bool EquivalenceSource::Initialize(BufferSource* source) { + return patch::ParseBuffer(source, &src_skip_) && + patch::ParseBuffer(source, &dst_skip_) && + patch::ParseBuffer(source, ©_count_); +} + +base::Optional<Equivalence> EquivalenceSource::GetNext() { + if (src_skip_.empty() || dst_skip_.empty() || copy_count_.empty()) + return base::nullopt; + + Equivalence equivalence = {}; + + uint32_t length = 0; + if (!patch::ParseVarUInt<uint32_t>(©_count_, &length)) + return base::nullopt; + equivalence.length = base::strict_cast<offset_t>(length); + + int32_t src_offset_diff = 0; // Intentionally signed. + if (!patch::ParseVarInt<int32_t>(&src_skip_, &src_offset_diff)) + return base::nullopt; + base::CheckedNumeric<offset_t> src_offset = + previous_src_offset_ + src_offset_diff; + if (!src_offset.IsValid()) + return base::nullopt; + + equivalence.src_offset = src_offset.ValueOrDie(); + previous_src_offset_ = src_offset + equivalence.length; + if (!previous_src_offset_.IsValid()) + return base::nullopt; + + uint32_t dst_offset_diff = 0; // Intentionally unsigned. + if (!patch::ParseVarUInt<uint32_t>(&dst_skip_, &dst_offset_diff)) + return base::nullopt; + base::CheckedNumeric<offset_t> dst_offset = + previous_dst_offset_ + dst_offset_diff; + if (!dst_offset.IsValid()) + return base::nullopt; + + equivalence.dst_offset = dst_offset.ValueOrDie(); + previous_dst_offset_ = equivalence.dst_offset + equivalence.length; + if (!previous_dst_offset_.IsValid()) + return base::nullopt; + + return equivalence; +} + +/******** ExtraDataSource ********/ + +ExtraDataSource::ExtraDataSource() = default; +ExtraDataSource::ExtraDataSource(const ExtraDataSource&) = default; +ExtraDataSource::~ExtraDataSource() = default; + +bool ExtraDataSource::Initialize(BufferSource* source) { + return patch::ParseBuffer(source, &extra_data_); +} + +base::Optional<ConstBufferView> ExtraDataSource::GetNext(offset_t size) { + DCHECK_GT(size, offset_t(0)); + ConstBufferView buffer; + if (!extra_data_.GetRegion(size, &buffer)) + return base::nullopt; + return buffer; +} + +/******** RawDeltaSource ********/ + +RawDeltaSource::RawDeltaSource() = default; +RawDeltaSource::RawDeltaSource(const RawDeltaSource&) = default; +RawDeltaSource::~RawDeltaSource() = default; + +bool RawDeltaSource::Initialize(BufferSource* source) { + return patch::ParseBuffer(source, &raw_delta_skip_) && + patch::ParseBuffer(source, &raw_delta_diff_); +} + +base::Optional<RawDeltaUnit> RawDeltaSource::GetNext() { + if (raw_delta_skip_.empty() || raw_delta_diff_.empty()) + return base::nullopt; + + RawDeltaUnit delta = {}; + uint32_t copy_offset_diff = 0; + if (!patch::ParseVarUInt<uint32_t>(&raw_delta_skip_, ©_offset_diff)) + return base::nullopt; + base::CheckedNumeric<offset_t> copy_offset = + copy_offset_diff + copy_offset_compensation_; + if (!copy_offset.IsValid()) + return base::nullopt; + delta.copy_offset = copy_offset.ValueOrDie(); + + if (!raw_delta_diff_.GetValue<int8_t>(&delta.diff)) + return base::nullopt; + + // We keep track of the compensation needed for next offset, taking into + // accound delta encoding and bias of -1. + copy_offset_compensation_ = copy_offset + 1; + if (!copy_offset_compensation_.IsValid()) + return base::nullopt; + return delta; +} + +/******** ReferenceDeltaSource ********/ + +ReferenceDeltaSource::ReferenceDeltaSource() = default; +ReferenceDeltaSource::ReferenceDeltaSource(const ReferenceDeltaSource&) = + default; +ReferenceDeltaSource::~ReferenceDeltaSource() = default; + +bool ReferenceDeltaSource::Initialize(BufferSource* source) { + return patch::ParseBuffer(source, &reference_delta_); +} + +base::Optional<int32_t> ReferenceDeltaSource::GetNext() { + if (reference_delta_.empty()) + return base::nullopt; + int32_t delta = 0; + if (!patch::ParseVarInt<int32_t>(&reference_delta_, &delta)) + return base::nullopt; + return delta; +} + +/******** TargetSource ********/ + +TargetSource::TargetSource() = default; +TargetSource::TargetSource(const TargetSource&) = default; +TargetSource::~TargetSource() = default; + +bool TargetSource::Initialize(BufferSource* source) { + return patch::ParseBuffer(source, &extra_targets_); +} + +base::Optional<offset_t> TargetSource::GetNext() { + if (extra_targets_.empty()) + return base::nullopt; + + uint32_t target_diff = 0; + if (!patch::ParseVarUInt<uint32_t>(&extra_targets_, &target_diff)) + return base::nullopt; + base::CheckedNumeric<offset_t> target = target_diff + target_compensation_; + if (!target.IsValid()) + return base::nullopt; + + // We keep track of the compensation needed for next target, taking into + // accound delta encoding and bias of -1. + target_compensation_ = target + 1; + if (!target_compensation_.IsValid()) + return base::nullopt; + return offset_t(target.ValueOrDie()); +} + +/******** PatchElementReader ********/ + +PatchElementReader::PatchElementReader() = default; +PatchElementReader::PatchElementReader(PatchElementReader&&) = default; +PatchElementReader::~PatchElementReader() = default; + +bool PatchElementReader::Initialize(BufferSource* source) { + bool ok = patch::ParseElementMatch(source, &element_match_) && + equivalences_.Initialize(source) && + extra_data_.Initialize(source) && raw_delta_.Initialize(source) && + reference_delta_.Initialize(source); + if (!ok) + return false; + uint32_t pool_count = 0; + if (!source->GetValue(&pool_count)) { + LOG(ERROR) << "Impossible to read pool_count from source."; + return false; + } + for (uint32_t i = 0; i < pool_count; ++i) { + uint8_t pool_tag_value = 0; + if (!source->GetValue(&pool_tag_value)) { + LOG(ERROR) << "Impossible to read pool_tag from source."; + return false; + } + + if (pool_tag_value >= extra_targets_.size()) + extra_targets_.resize(pool_tag_value + 1); + + if (!extra_targets_[pool_tag_value].Initialize(source)) + return false; + } + return true; +} + +/******** EnsemblePatchReader ********/ + +base::Optional<EnsemblePatchReader> EnsemblePatchReader::Create( + ConstBufferView buffer) { + BufferSource source(buffer); + EnsemblePatchReader patch; + if (!patch.Initialize(&source)) + return base::nullopt; + return patch; +} + +EnsemblePatchReader::EnsemblePatchReader() = default; +EnsemblePatchReader::EnsemblePatchReader(EnsemblePatchReader&&) = default; +EnsemblePatchReader::~EnsemblePatchReader() = default; + +bool EnsemblePatchReader::Initialize(BufferSource* source) { + if (!source->GetValue(&header_)) { + LOG(ERROR) << "Impossible to read header from source."; + return false; + } + if (header_.magic != PatchHeader::kMagic) { + LOG(ERROR) << "Patch contains invalid magic."; + return false; + } + uint32_t patch_type_int = + static_cast<uint32_t>(PatchType::kUnrecognisedPatch); + if (!source->GetValue(&patch_type_int)) { + LOG(ERROR) << "Impossible to read patch_type from source."; + return false; + } + patch_type_ = static_cast<PatchType>(patch_type_int); + if (patch_type_ != PatchType::kRawPatch && + patch_type_ != PatchType::kSinglePatch && + patch_type_ != PatchType::kEnsemblePatch) { + LOG(ERROR) << "Invalid patch_type encountered."; + return false; + } + + uint32_t element_count = 0; + if (!source->GetValue(&element_count)) { + LOG(ERROR) << "Impossible to read element_count from source."; + return false; + } + if (patch_type_ == PatchType::kRawPatch || + patch_type_ == PatchType::kSinglePatch) { + if (element_count != 1) { + LOG(ERROR) << "Unexpected number of elements in patch."; + return false; // Only one element expected. + } + } + + elements_.reserve(element_count); + offset_t current_dst_offset = 0; + for (uint32_t i = 0; i < element_count; ++i) { + PatchElementReader element_patch; + if (!element_patch.Initialize(source)) + return false; + + if (!element_patch.old_element().FitsIn(header_.old_size) || + !element_patch.new_element().FitsIn(header_.new_size)) { + LOG(ERROR) << "Invalid element encountered."; + return false; + } + + if (element_patch.new_element().offset != current_dst_offset) { + LOG(ERROR) << "Invalid element encountered."; + return false; + } + current_dst_offset = element_patch.new_element().EndOffset(); + + elements_.push_back(std::move(element_patch)); + } + if (current_dst_offset != header_.new_size) { + LOG(ERROR) << "Patch elements don't fully cover new image file."; + return false; + } + + if (!source->empty()) { + LOG(ERROR) << "Patch was not fully consumed."; + return false; + } + + return true; +} + +bool EnsemblePatchReader::CheckOldFile(ConstBufferView old_image) const { + return old_image.size() == header_.old_size && + CalculateCrc32(old_image.begin(), old_image.end()) == header_.old_crc; +} + +bool EnsemblePatchReader::CheckNewFile(ConstBufferView new_image) const { + return new_image.size() == header_.new_size && + CalculateCrc32(new_image.begin(), new_image.end()) == header_.new_crc; +} + +} // namespace zucchini
diff --git a/chrome/installer/zucchini/patch_reader.h b/chrome/installer/zucchini/patch_reader.h new file mode 100644 index 0000000..c326acae --- /dev/null +++ b/chrome/installer/zucchini/patch_reader.h
@@ -0,0 +1,275 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_INSTALLER_ZUCCHINI_PATCH_READER_H_ +#define CHROME_INSTALLER_ZUCCHINI_PATCH_READER_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <vector> + +#include "base/debug/stack_trace.h" +#include "base/logging.h" +#include "base/numerics/checked_math.h" +#include "base/optional.h" +#include "chrome/installer/zucchini/buffer_source.h" +#include "chrome/installer/zucchini/buffer_view.h" +#include "chrome/installer/zucchini/image_utils.h" +#include "chrome/installer/zucchini/patch_utils.h" + +namespace zucchini { + +namespace patch { + +// The Parse*() functions below attempt to extract data of a specific type from +// the beginning of |source|. A parse function: On success, consumes the used +// portion of |source|, writes data into the output parameter, and returns +// true. Otherwise returns false and does not consume |source|. + +// Parses |source| for the next ElementMatch. +bool ParseElementMatch(BufferSource* source, ElementMatch* element_match); + +// Parses |source| for the next embedded BufferSource. +bool ParseBuffer(BufferSource* source, BufferSource* buffer); + +// Parses |source| for the next VarUInt. +template <class T> +bool ParseVarUInt(BufferSource* source, T* value) { + auto bytes_read = DecodeVarUInt(source->begin(), source->end(), value); + if (!bytes_read) { + LOG(ERROR) << "Impossible to read VarUInt from source."; + LOG(ERROR) << base::debug::StackTrace().ToString(); + return false; + } + // Advance |source| beyond the VarUInt value. + source->Skip(bytes_read); + return true; +} + +// Parses |source| for the next VarInt. +template <class T> +bool ParseVarInt(BufferSource* source, T* value) { + auto bytes_read = DecodeVarInt(source->begin(), source->end(), value); + if (!bytes_read) { + LOG(ERROR) << "Impossible to read VarInt from source."; + LOG(ERROR) << base::debug::StackTrace().ToString(); + return false; + } + // Advance |source| beyond the VarInt value. + source->Skip(bytes_read); + return true; +} + +} // namespace patch + +// Each of *Source classes below has an associated "main type", and performs the +// following: +// - Consumes portions of a BufferSource (required to remain valid for the +// lifetime of the object). +// - Decodes consumed data, which represent a list of items with "main type". +// - Dispenses "main type" elements (hence "Source" in the name). +// +// Common "core functions" implemented by *Source classes are: +// - bool Initialize(BufferSource* source): Consumes data from BufferSource and +// initializes internal states. Returns true if successful, and false +// otherwise (|source| may be partially consumed). +// - base::Optional<MAIN_TYPE> GetNext(OPT_PARAMS): Decodes consumed data and +// returns the next item as base::Optional (returns base::nullopt on failure). +// - bool Done() const: Returns true if no more items remain; otherwise false. +// +// Usage of *Source instances don't mix, and GetNext() have dissimilar +// interfaces. Therefore we do not use inheritance to relate *Source classes, +// and simply implement "core functions" with matching names. + +// Source for Equivalences. +class EquivalenceSource { + public: + EquivalenceSource(); + EquivalenceSource(const EquivalenceSource&); + ~EquivalenceSource(); + + // Core functions. + bool Initialize(BufferSource* source); + base::Optional<Equivalence> GetNext(); + bool Done() const { + return src_skip_.empty() && dst_skip_.empty() && copy_count_.empty(); + } + + // Accessors for unittest. + BufferSource src_skip() const { return src_skip_; } + BufferSource dst_skip() const { return dst_skip_; } + BufferSource copy_count() const { return copy_count_; } + + private: + BufferSource src_skip_; + BufferSource dst_skip_; + BufferSource copy_count_; + + base::CheckedNumeric<offset_t> previous_src_offset_ = 0; + base::CheckedNumeric<offset_t> previous_dst_offset_ = 0; +}; + +// Source for extra data. +class ExtraDataSource { + public: + ExtraDataSource(); + ExtraDataSource(const ExtraDataSource&); + ~ExtraDataSource(); + + // Core functions. + bool Initialize(BufferSource* source); + // |size| is the size in bytes of the buffer requested. + base::Optional<ConstBufferView> GetNext(offset_t size); + bool Done() const { return extra_data_.empty(); } + + // Accessors for unittest. + BufferSource extra_data() const { return extra_data_; } + + private: + BufferSource extra_data_; +}; + +// Source for raw delta. +class RawDeltaSource { + public: + RawDeltaSource(); + RawDeltaSource(const RawDeltaSource&); + ~RawDeltaSource(); + + // Core functions. + bool Initialize(BufferSource* source); + base::Optional<RawDeltaUnit> GetNext(); + bool Done() const { + return raw_delta_skip_.empty() && raw_delta_diff_.empty(); + } + + // Accessors for unittest. + BufferSource raw_delta_skip() const { return raw_delta_skip_; } + BufferSource raw_delta_diff() const { return raw_delta_diff_; } + + private: + BufferSource raw_delta_skip_; + BufferSource raw_delta_diff_; + + base::CheckedNumeric<offset_t> copy_offset_compensation_ = 0; +}; + +// Source for reference delta. +class ReferenceDeltaSource { + public: + ReferenceDeltaSource(); + ReferenceDeltaSource(const ReferenceDeltaSource&); + ~ReferenceDeltaSource(); + + // Core functions. + bool Initialize(BufferSource* source); + base::Optional<int32_t> GetNext(); + bool Done() const { return reference_delta_.empty(); } + + // Accessors for unittest. + BufferSource reference_delta() const { return reference_delta_; } + + private: + BufferSource reference_delta_; +}; + +// Source for additional targets. +class TargetSource { + public: + TargetSource(); + TargetSource(const TargetSource&); + ~TargetSource(); + + // Core functions. + bool Initialize(BufferSource* source); + base::Optional<offset_t> GetNext(); + bool Done() const { return extra_targets_.empty(); } + + // Accessors for unittest. + BufferSource extra_targets() const { return extra_targets_; } + + private: + BufferSource extra_targets_; + + base::CheckedNumeric<offset_t> target_compensation_ = 0; +}; + +// Following are utility classes providing a structured view on data forming a +// patch. + +// Utility to read a patch element. A patch element contains all the information +// necessary to patch a single element. This class provide access +// to the multiple streams of data forming the patch element. +class PatchElementReader { + public: + PatchElementReader(); + PatchElementReader(PatchElementReader&&); + ~PatchElementReader(); + + // If data read from |source| is well-formed, initialize internal state to + // read from it, and returns true. Otherwise returns false. + bool Initialize(BufferSource* source); + + const ElementMatch& element_match() const { return element_match_; } + const Element& old_element() const { return element_match_.old_element; } + const Element& new_element() const { return element_match_.new_element; } + size_t pool_count() const { return extra_targets_.size(); } + + const EquivalenceSource& GetEquivalenceSource() const { + return equivalences_; + } + const ExtraDataSource& GetExtraDataSource() const { return extra_data_; } + const RawDeltaSource& GetRawDeltaSource() const { return raw_delta_; } + const ReferenceDeltaSource& GetReferenceDeltaSource() const { + return reference_delta_; + } + const TargetSource& GetExtraTargetSource(PoolTag tag) const { + DCHECK_LT(tag.value(), extra_targets_.size()); + return extra_targets_[tag.value()]; + } + + private: + ElementMatch element_match_; + EquivalenceSource equivalences_; + ExtraDataSource extra_data_; + RawDeltaSource raw_delta_; + ReferenceDeltaSource reference_delta_; + std::vector<TargetSource> extra_targets_; +}; + +// Utility to read a Zucchini ensemble patch. An ensemble patch is the +// concatenation of a patch header with a vector of patch elements. +class EnsemblePatchReader { + public: + // If data read from |buffer| is well-formed, initializes and returns + // an instance of EnsemblePatchReader. Otherwise returns base::nullopt. + static base::Optional<EnsemblePatchReader> Create(ConstBufferView buffer); + + EnsemblePatchReader(); + EnsemblePatchReader(EnsemblePatchReader&&); + ~EnsemblePatchReader(); + + // If data read from |source| is well-formed, initialize internal state to + // read from it, and returns true. Otherwise returns false. + bool Initialize(BufferSource* source); + + // Check old / new image file validity, comparing against expected size and + // CRC32. Return true if file matches expectations, false otherwise. + bool CheckOldFile(ConstBufferView old_image) const; + bool CheckNewFile(ConstBufferView old_image) const; + + const PatchHeader& header() const { return header_; } + PatchType patch_type() const { return patch_type_; } + const std::vector<PatchElementReader>& elements() const { return elements_; } + + private: + PatchHeader header_; + PatchType patch_type_; + std::vector<PatchElementReader> elements_; +}; + +} // namespace zucchini + +#endif // CHROME_INSTALLER_ZUCCHINI_PATCH_READER_H_
diff --git a/chrome/installer/zucchini/patch_utils.h b/chrome/installer/zucchini/patch_utils.h index 8a65bc09..23be01c 100644 --- a/chrome/installer/zucchini/patch_utils.h +++ b/chrome/installer/zucchini/patch_utils.h
@@ -7,20 +7,28 @@ #include <stdint.h> +#include <iterator> #include <type_traits> -#include "base/logging.h" -#include "base/optional.h" #include "chrome/installer/zucchini/image_utils.h" namespace zucchini { // Constants that appear inside a patch. enum class PatchType : uint32_t { + // Patch contains a single raw element, corresponding to an element match that + // covers the entire images, and with ExecutableType::kExeTypeNoOp. kRawPatch = 0, + + // Patch contains a single executable element, corresponding to an element + // match that covers the entire images. kSinglePatch = 1, + + // Patch contains multiple raw and/or executable elements. kEnsemblePatch = 2, - kUnrecognisedPatch, + + // Used when type is uninitialized. + kUnrecognisedPatch }; // A Zucchini 'ensemble' patch is the concatenation of a patch header with a @@ -33,7 +41,7 @@ // Header for a Zucchini patch, found at the begining of an ensemble patch. struct PatchHeader { // Magic signature at the beginning of a Zucchini patch file. - static constexpr uint32_t kMagic = 'Z' | ('u' << 8) | ('c' << 16); + enum : uint32_t { kMagic = 'Z' | ('u' << 8) | ('c' << 16) }; uint32_t magic = 0; uint32_t old_size = 0; @@ -49,26 +57,25 @@ struct PatchElementHeader { uint32_t old_offset; uint32_t new_offset; - uint64_t old_length; - uint64_t new_length; + uint32_t old_length; + uint32_t new_length; uint32_t exe_type; }; // Sanity check. -static_assert(sizeof(PatchElementHeader) == 28, +static_assert(sizeof(PatchElementHeader) == 20, "PatchElementHeader is 28 bytes"); #pragma pack(pop) // Descibes a raw FIX operation. struct RawDeltaUnit { - offset_t copy_offset; // Offset in copy regions starting from last delta. + offset_t copy_offset; // Offset in copy regions. int8_t diff; // Bytewise difference. }; // A Zucchini patch contains data streams encoded using varint format to reduce -// uncompressed size. This is a variable-length encoding for integer quantities -// that strips away leading (most-significant) null bytes. +// uncompressed size. // Writes |value| as a varint in |dst| and returns an iterator pointing beyond // the written region. |dst| is assumed to hold enough space. Typically, this @@ -78,8 +85,8 @@ It EncodeVarUInt(T value, It dst) { static_assert(std::is_unsigned<T>::value, "Value type must be unsigned"); - while (value >= 128) { - *dst++ = static_cast<uint8_t>(value) | 128; + while (value >= 0x80) { + *dst++ = static_cast<uint8_t>(value) | 0x80; value >>= 7; } *dst++ = static_cast<uint8_t>(value); @@ -98,44 +105,45 @@ return EncodeVarUInt(unsigned_value_type(value) << 1, dst); } -// Tries to read a varint unsigned integer from [|first|, |last|). If -// succesfull, writes result into |value| and returns an iterator pointing -// beyond the formatted varint. Otherwise returns nullopt. +// Tries to read a varint unsigned integer from |[first, last)|. If +// succesful, writes result into |value| and returns the number of bytes +// read from |[first, last)|. Otherwise returns 0. template <class T, class It> -base::Optional<It> DecodeVarUInt(It first, It last, T* value) { +typename std::iterator_traits<It>::difference_type DecodeVarUInt(It first, + It last, + T* value) { static_assert(std::is_unsigned<T>::value, "Value type must be unsigned"); uint8_t sh = 0; T val = 0; - while (first != last) { - val |= T(*first & 0x7F) << sh; - if (*(first++) < 0x80) { + for (auto it = first; it != last;) { + val |= T(*it & 0x7F) << sh; + if (*(it++) < 0x80) { *value = val; - return first; + return it - first; } sh += 7; - if (sh >= sizeof(T) * 8) { // Overflow! - LOG(ERROR) << "Overflow encountered."; - return base::nullopt; - } + if (sh >= sizeof(T) * 8) // Overflow! + return 0; } - LOG(ERROR) << "Exhausted data while reading."; - return base::nullopt; + return 0; } // Same as DecodeVarUInt(), but for signed values. template <class T, class It> -base::Optional<It> DecodeVarInt(It first, It last, T* value) { +typename std::iterator_traits<It>::difference_type DecodeVarInt(It first, + It last, + T* value) { static_assert(std::is_signed<T>::value, "Value type must be signed"); typename std::make_unsigned<T>::type tmp = 0; auto res = DecodeVarUInt(first, last, &tmp); - if (!res) - return res; - if (tmp & 1) - *value = ~static_cast<T>(tmp >> 1); - else - *value = static_cast<T>(tmp >> 1); + if (res) { + if (tmp & 1) + *value = ~static_cast<T>(tmp >> 1); + else + *value = static_cast<T>(tmp >> 1); + } return res; }
diff --git a/chrome/installer/zucchini/patch_utils_unittest.cc b/chrome/installer/zucchini/patch_utils_unittest.cc index 5e65e67..e4ecf0c 100644 --- a/chrome/installer/zucchini/patch_utils_unittest.cc +++ b/chrome/installer/zucchini/patch_utils_unittest.cc
@@ -9,7 +9,6 @@ #include <iterator> #include <vector> -#include "base/test/gtest_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace zucchini { @@ -38,16 +37,16 @@ for (T expected : values) { T value = T(-1); auto res = DecodeVarUInt(it, buffer.end(), &value); - EXPECT_TRUE(res.has_value()); + EXPECT_NE(0, res); EXPECT_EQ(expected, value); - it = res.value(); + it += res; } EXPECT_EQ(it, buffer.end()); - T dummy = T(-1); - auto res = DecodeVarUInt(it, buffer.end(), &dummy); - EXPECT_EQ(base::nullopt, res); - EXPECT_EQ(T(-1), dummy); + T value = T(-1); + auto res = DecodeVarUInt(it, buffer.end(), &value); + EXPECT_EQ(0, res); + EXPECT_EQ(T(-1), value); } template <class T> @@ -74,19 +73,21 @@ for (T expected : values) { T value = T(-1); auto res = DecodeVarInt(it, buffer.end(), &value); - EXPECT_TRUE(res.has_value()); + EXPECT_NE(0, res); EXPECT_EQ(expected, value); - it = res.value(); + it += res; } - T dummy = T(-1); - auto res = DecodeVarInt(it, buffer.end(), &dummy); - EXPECT_EQ(base::nullopt, res); - EXPECT_EQ(T(-1), dummy); + EXPECT_EQ(it, buffer.end()); + + T value = T(-1); + auto res = DecodeVarInt(it, buffer.end(), &value); + EXPECT_EQ(0, res); + EXPECT_EQ(T(-1), value); } TEST(PatchUtilsTest, EncodeDecodeVarUInt32) { TestEncodeDecodeVarUInt<uint32_t>({0, 64, 128, 8192, 16384, 1 << 20, 1 << 21, - 1 << 22, 1 << 27, 1 << 28, 0x7FFFFFFF, + 1 << 22, 1 << 27, 1 << 28, 0x7FFFFFFFU, UINT32_MAX}); } @@ -99,7 +100,7 @@ TEST(PatchUtilsTest, EncodeDecodeVarUInt64) { TestEncodeDecodeVarUInt<uint64_t>({0, 64, 128, 8192, 16384, 1 << 20, 1 << 21, 1 << 22, 1ULL << 55, 1ULL << 56, - 0x7FFFFFFFFFFFFFFF, UINT64_MAX}); + 0x7FFFFFFFFFFFFFFFULL, UINT64_MAX}); } TEST(PatchUtilsTest, EncodeDecodeVarInt64) { @@ -109,55 +110,62 @@ } TEST(PatchUtilsTest, DecodeVarUInt32Malformed) { - // Dummy variable to ensure that on failure, the output variable is not - // written to. - uint32_t dummy = uint32_t(-1); + constexpr uint32_t kUninit = static_cast<uint32_t>(-1LL); - auto TestDecodeVarInt = [&dummy](const std::vector<uint8_t>& buffer) { - dummy = uint32_t(-1); - return DecodeVarUInt(buffer.begin(), buffer.end(), &dummy); + // Output variable to ensure that on failure, the output variable is not + // written to. + uint32_t value = uint32_t(-1); + + auto TestDecodeVarInt = [&value, + kUninit](const std::vector<uint8_t>& buffer) { + value = kUninit; + return DecodeVarUInt(buffer.begin(), buffer.end(), &value); }; // Exhausted. - EXPECT_EQ(base::nullopt, TestDecodeVarInt(std::vector<uint8_t>{})); - EXPECT_EQ(uint32_t(-1), dummy); - EXPECT_EQ(base::nullopt, TestDecodeVarInt(std::vector<uint8_t>(4, 128))); - EXPECT_EQ(uint32_t(-1), dummy); + EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>{})); + EXPECT_EQ(kUninit, value); + EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>(4, 128))); + EXPECT_EQ(kUninit, value); // Overflow. - EXPECT_EQ(base::nullopt, TestDecodeVarInt(std::vector<uint8_t>(6, 128))); - EXPECT_EQ(uint32_t(-1), dummy); - EXPECT_EQ(base::nullopt, TestDecodeVarInt({128, 128, 128, 128, 128, 42})); - EXPECT_EQ(uint32_t(-1), dummy); + EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>(6, 128))); + EXPECT_EQ(kUninit, value); + EXPECT_EQ(0, TestDecodeVarInt({128, 128, 128, 128, 128, 42})); + EXPECT_EQ(kUninit, value); // Following are pathological cases that are not handled for simplicity, // hence decoding is expected to be successful. - EXPECT_NE(base::nullopt, TestDecodeVarInt({128, 128, 128, 128, 16})); - EXPECT_EQ(uint32_t(0), dummy); - EXPECT_NE(base::nullopt, TestDecodeVarInt({128, 128, 128, 128, 32})); - EXPECT_EQ(uint32_t(0), dummy); - EXPECT_NE(base::nullopt, TestDecodeVarInt({128, 128, 128, 128, 64})); - EXPECT_EQ(uint32_t(0), dummy); + EXPECT_NE(0, TestDecodeVarInt({128, 128, 128, 128, 16})); + EXPECT_EQ(uint32_t(0), value); + EXPECT_NE(0, TestDecodeVarInt({128, 128, 128, 128, 32})); + EXPECT_EQ(uint32_t(0), value); + EXPECT_NE(0, TestDecodeVarInt({128, 128, 128, 128, 64})); + EXPECT_EQ(uint32_t(0), value); } TEST(PatchUtilsTest, DecodeVarUInt64Malformed) { - uint64_t dummy = uint64_t(-1); - auto TestDecodeVarInt = [&dummy](const std::vector<uint8_t>& buffer) { - return DecodeVarUInt(buffer.begin(), buffer.end(), &dummy); + constexpr uint64_t kUninit = static_cast<uint64_t>(-1); + + uint64_t value = kUninit; + auto TestDecodeVarInt = [&value, + kUninit](const std::vector<uint8_t>& buffer) { + value = kUninit; + return DecodeVarUInt(buffer.begin(), buffer.end(), &value); }; // Exhausted. - EXPECT_EQ(base::nullopt, TestDecodeVarInt(std::vector<uint8_t>{})); - EXPECT_EQ(uint64_t(-1), dummy); - EXPECT_EQ(base::nullopt, TestDecodeVarInt(std::vector<uint8_t>(9, 128))); - EXPECT_EQ(uint64_t(-1), dummy); + EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>{})); + EXPECT_EQ(kUninit, value); + EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>(9, 128))); + EXPECT_EQ(kUninit, value); // Overflow. - EXPECT_EQ(base::nullopt, TestDecodeVarInt(std::vector<uint8_t>(10, 128))); - EXPECT_EQ(uint64_t(-1), dummy); - EXPECT_EQ(base::nullopt, TestDecodeVarInt({128, 128, 128, 128, 128, 128, 128, - 128, 128, 128, 42})); - EXPECT_EQ(uint64_t(-1), dummy); + EXPECT_EQ(0, TestDecodeVarInt(std::vector<uint8_t>(10, 128))); + EXPECT_EQ(kUninit, value); + EXPECT_EQ(0, TestDecodeVarInt( + {128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 42})); + EXPECT_EQ(kUninit, value); } } // namespace zucchini
diff --git a/chrome/installer/zucchini/patch_writer.cc b/chrome/installer/zucchini/patch_writer.cc new file mode 100644 index 0000000..42a8240 --- /dev/null +++ b/chrome/installer/zucchini/patch_writer.cc
@@ -0,0 +1,290 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/installer/zucchini/patch_writer.h" + +#include <algorithm> +#include <iterator> + +#include "base/numerics/checked_math.h" +#include "base/numerics/safe_conversions.h" +#include "chrome/installer/zucchini/crc32.h" + +namespace zucchini { + +namespace patch { + +bool SerializeElementMatch(const ElementMatch& element_match, + BufferSink* sink) { + if (!element_match.IsValid()) + return false; + + PatchElementHeader element_header; + element_header.old_offset = element_match.old_element.offset; + element_header.new_offset = element_match.new_element.offset; + element_header.old_length = element_match.old_element.length; + element_header.new_length = element_match.new_element.length; + element_header.exe_type = element_match.old_element.exe_type; + + return sink->PutValue<PatchElementHeader>(element_header); +} + +size_t SerializedElementMatchSize(const ElementMatch& element_match) { + return sizeof(PatchElementHeader); +} + +bool SerializeBuffer(const std::vector<uint8_t>& buffer, BufferSink* sink) { + // buffer.size() is not encoded as varint to simplify SerializedBufferSize(). + base::CheckedNumeric<uint32_t> size = buffer.size(); + if (!size.IsValid()) + return false; + return sink->PutValue<uint32_t>(size.ValueOrDie()) && + sink->PutRange(buffer.begin(), buffer.end()); +} + +size_t SerializedBufferSize(const std::vector<uint8_t>& buffer) { + return sizeof(uint32_t) + buffer.size(); +} + +} // namespace patch + +/******** EquivalenceSink ********/ + +EquivalenceSink::EquivalenceSink() = default; +EquivalenceSink::EquivalenceSink(const std::vector<uint8_t>& src_skip, + const std::vector<uint8_t>& dst_skip, + const std::vector<uint8_t>& copy_count) + : src_skip_(src_skip), dst_skip_(dst_skip), copy_count_(copy_count) {} + +EquivalenceSink::EquivalenceSink(EquivalenceSink&&) = default; +EquivalenceSink::~EquivalenceSink() = default; + +void EquivalenceSink::PutNext(const Equivalence& equivalence) { + // Equivalences are expected to be given ordered by |dst_offset|. + DCHECK_GE(equivalence.dst_offset, dst_offset_); + // Unsigned values are ensured by above check. + + // Result of substracting 2 unsigned integers is unsigned. Overflow is allowed + // for negative values, as long as uint32_t can hold the result. + uint32_t src_offset_diff = + base::strict_cast<uint32_t>(equivalence.src_offset - src_offset_); + EncodeVarInt<int32_t>(static_cast<int32_t>(src_offset_diff), + std::back_inserter(src_skip_)); + + EncodeVarUInt<uint32_t>( + base::strict_cast<uint32_t>(equivalence.dst_offset - dst_offset_), + std::back_inserter(dst_skip_)); + + EncodeVarUInt<uint32_t>(base::strict_cast<uint32_t>(equivalence.length), + std::back_inserter(copy_count_)); + + src_offset_ = equivalence.src_offset + equivalence.length; + dst_offset_ = equivalence.dst_offset + equivalence.length; +} + +size_t EquivalenceSink::SerializedSize() const { + return patch::SerializedBufferSize(src_skip_) + + patch::SerializedBufferSize(dst_skip_) + + patch::SerializedBufferSize(copy_count_); +} + +bool EquivalenceSink::SerializeInto(BufferSink* sink) const { + return patch::SerializeBuffer(src_skip_, sink) && + patch::SerializeBuffer(dst_skip_, sink) && + patch::SerializeBuffer(copy_count_, sink); +} + +/******** ExtraDataSink ********/ + +ExtraDataSink::ExtraDataSink() = default; +ExtraDataSink::ExtraDataSink(const std::vector<uint8_t>& extra_data) + : extra_data_(extra_data) {} + +ExtraDataSink::ExtraDataSink(ExtraDataSink&&) = default; +ExtraDataSink::~ExtraDataSink() = default; + +void ExtraDataSink::PutNext(ConstBufferView region) { + extra_data_.insert(extra_data_.end(), region.begin(), region.end()); +} + +size_t ExtraDataSink::SerializedSize() const { + return patch::SerializedBufferSize(extra_data_); +} + +bool ExtraDataSink::SerializeInto(BufferSink* sink) const { + return patch::SerializeBuffer(extra_data_, sink); +} + +/******** RawDeltaSink ********/ + +RawDeltaSink::RawDeltaSink() = default; +RawDeltaSink::RawDeltaSink(const std::vector<uint8_t>& raw_delta_skip, + const std::vector<uint8_t>& raw_delta_diff) + : raw_delta_skip_(raw_delta_skip), raw_delta_diff_(raw_delta_diff) {} + +RawDeltaSink::RawDeltaSink(RawDeltaSink&&) = default; +RawDeltaSink::~RawDeltaSink() = default; + +void RawDeltaSink::PutNext(const RawDeltaUnit& delta) { + DCHECK_GE(delta.copy_offset, copy_offset_compensation_); + EncodeVarUInt<uint32_t>(base::strict_cast<uint32_t>( + delta.copy_offset - copy_offset_compensation_), + std::back_inserter(raw_delta_skip_)); + + copy_offset_compensation_ = delta.copy_offset + 1; + + raw_delta_diff_.push_back(delta.diff); +} + +size_t RawDeltaSink::SerializedSize() const { + return patch::SerializedBufferSize(raw_delta_skip_) + + patch::SerializedBufferSize(raw_delta_diff_); +} + +bool RawDeltaSink::SerializeInto(BufferSink* sink) const { + return patch::SerializeBuffer(raw_delta_skip_, sink) && + patch::SerializeBuffer(raw_delta_diff_, sink); +} + +/******** ReferenceDeltaSink ********/ + +ReferenceDeltaSink::ReferenceDeltaSink() = default; +ReferenceDeltaSink::ReferenceDeltaSink( + const std::vector<uint8_t>& reference_delta) + : reference_delta_(reference_delta) {} + +ReferenceDeltaSink::ReferenceDeltaSink(ReferenceDeltaSink&&) = default; +ReferenceDeltaSink::~ReferenceDeltaSink() = default; + +void ReferenceDeltaSink::PutNext(int32_t diff) { + EncodeVarInt<int32_t>(diff, std::back_inserter(reference_delta_)); +} + +size_t ReferenceDeltaSink::SerializedSize() const { + return patch::SerializedBufferSize(reference_delta_); +} + +bool ReferenceDeltaSink::SerializeInto(BufferSink* sink) const { + return patch::SerializeBuffer(reference_delta_, sink); +} + +/******** TargetSink ********/ + +TargetSink::TargetSink() = default; +TargetSink::TargetSink(const std::vector<uint8_t>& extra_targets) + : extra_targets_(extra_targets) {} + +TargetSink::TargetSink(TargetSink&&) = default; +TargetSink::~TargetSink() = default; + +void TargetSink::PutNext(uint32_t target) { + DCHECK_GE(target, target_compensation_); + + EncodeVarUInt<uint32_t>( + base::strict_cast<uint32_t>(target - target_compensation_), + std::back_inserter(extra_targets_)); + + target_compensation_ = target + 1; +} + +size_t TargetSink::SerializedSize() const { + return patch::SerializedBufferSize(extra_targets_); +} + +bool TargetSink::SerializeInto(BufferSink* sink) const { + return patch::SerializeBuffer(extra_targets_, sink); +} + +/******** PatchElementWriter ********/ + +PatchElementWriter::PatchElementWriter() = default; +PatchElementWriter::PatchElementWriter(ElementMatch element_match) + : element_match_(element_match) {} + +PatchElementWriter::PatchElementWriter(PatchElementWriter&&) = default; +PatchElementWriter::~PatchElementWriter() = default; + +size_t PatchElementWriter::SerializedSize() const { + size_t serialized_size = + patch::SerializedElementMatchSize(element_match_) + + equivalences_->SerializedSize() + extra_data_->SerializedSize() + + raw_delta_->SerializedSize() + reference_delta_->SerializedSize(); + + serialized_size += sizeof(uint32_t); + for (const auto& extra_symbols : extra_targets_) + serialized_size += extra_symbols.second.SerializedSize() + 1; + return serialized_size; +} + +bool PatchElementWriter::SerializeInto(BufferSink* sink) const { + bool ok = + patch::SerializeElementMatch(element_match_, sink) && + equivalences_->SerializeInto(sink) && extra_data_->SerializeInto(sink) && + raw_delta_->SerializeInto(sink) && reference_delta_->SerializeInto(sink); + if (!ok) + return false; + + if (!sink->PutValue<uint32_t>( + base::checked_cast<uint32_t>(extra_targets_.size()))) + return false; + for (const auto& extra_target_sink : extra_targets_) { + if (!sink->PutValue<uint8_t>(extra_target_sink.first.value())) + return false; + if (!extra_target_sink.second.SerializeInto(sink)) + return false; + } + return true; +} + +/******** EnsemblePatchWriter ********/ + +EnsemblePatchWriter::~EnsemblePatchWriter() = default; + +EnsemblePatchWriter::EnsemblePatchWriter(const PatchHeader& header) + : header_(header) { + DCHECK_EQ(header_.magic, PatchHeader::kMagic); +} + +EnsemblePatchWriter::EnsemblePatchWriter(ConstBufferView old_image, + ConstBufferView new_image) { + header_.magic = PatchHeader::kMagic; + header_.old_size = base::checked_cast<uint32_t>(old_image.size()); + header_.old_crc = CalculateCrc32(old_image.begin(), old_image.end()); + header_.new_size = base::checked_cast<uint32_t>(new_image.size()); + header_.new_crc = CalculateCrc32(new_image.begin(), new_image.end()); +} + +void EnsemblePatchWriter::AddElement(PatchElementWriter&& patch_element) { + DCHECK(patch_element.new_element().offset == current_dst_offset_); + current_dst_offset_ = patch_element.new_element().EndOffset(); + elements_.push_back(std::move(patch_element)); +} + +size_t EnsemblePatchWriter::SerializedSize() const { + size_t serialized_size = + sizeof(PatchHeader) + sizeof(PatchType) + sizeof(uint32_t); + for (const auto& patch_element : elements_) { + serialized_size += patch_element.SerializedSize(); + } + return serialized_size; +} + +bool EnsemblePatchWriter::SerializeInto(BufferSink* sink) const { + DCHECK_NE(patch_type_, PatchType::kUnrecognisedPatch); + DCHECK_EQ(current_dst_offset_, header_.new_size); + bool ok = + sink->PutValue<PatchHeader>(header_) && + sink->PutValue<PatchType>(patch_type_) && + sink->PutValue<uint32_t>(base::checked_cast<uint32_t>(elements_.size())); + if (!ok) + return false; + + for (const auto& element : elements_) { + if (!element.SerializeInto(sink)) + return false; + } + return true; +} + +} // namespace zucchini
diff --git a/chrome/installer/zucchini/patch_writer.h b/chrome/installer/zucchini/patch_writer.h new file mode 100644 index 0000000..f810a67 --- /dev/null +++ b/chrome/installer/zucchini/patch_writer.h
@@ -0,0 +1,276 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_INSTALLER_ZUCCHINI_PATCH_WRITER_H_ +#define CHROME_INSTALLER_ZUCCHINI_PATCH_WRITER_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <map> +#include <utility> +#include <vector> + +#include "base/logging.h" +#include "base/macros.h" +#include "base/optional.h" +#include "chrome/installer/zucchini/buffer_sink.h" +#include "chrome/installer/zucchini/buffer_view.h" +#include "chrome/installer/zucchini/image_utils.h" +#include "chrome/installer/zucchini/patch_utils.h" + +namespace zucchini { + +namespace patch { + +// If sufficient space is available, serializes |element_match| into |sink| and +// returns true. Otherwise returns false, and |sink| will be in an undefined +// state. +bool SerializeElementMatch(const ElementMatch& element_match, BufferSink* sink); + +// Returns the size in bytes required to serialize |element_match|. +size_t SerializedElementMatchSize(const ElementMatch& element_match); + +// If sufficient space is available, serializes |buffer| into |sink| and returns +// true. Otherwise returns false, and |sink| will be in an undefined state. +bool SerializeBuffer(const std::vector<uint8_t>& buffer, BufferSink* sink); + +// Returns the size in bytes required to serialize |buffer|. +size_t SerializedBufferSize(const std::vector<uint8_t>& buffer); + +} // namespace patch + +// Each of *Sink classes below has an associated "main type", and performs the +// following: +// - Receives multiple "main type" elements (hence "Sink" in the name). +// - Encodes list of received data, and writes them to internal storage (e.g., +// applying delta encoding). +// - Writes encoded data to BufferSink. +// +// Common "core functions" implemented for *Sink classes are: +// - void PutNext(const MAIN_TYPE& inst): Encodes and writes an instance of +// MAIN_TYPE to internal storage. Assumptions may be applied to successive +// |inst| provided. +// - size_t SerializedSize() const: Returns the serialized size in bytes of +// internal storage. +// - bool SerializeInto(BufferSink* sink) const: If |sink| has enough space, +// serializes internal storage into |sink|, and returns true. Otherwise +// returns false. +// +// Usage of *Sink instances don't mix, and PuttNext() have dissimilar +// interfaces. Therefore we do not use inheritance to relate *Sink classes, +// simply implement "core functions" with matching names. + +// Sink for equivalences. +class EquivalenceSink { + public: + EquivalenceSink(); + EquivalenceSink(const std::vector<uint8_t>& src_skip, + const std::vector<uint8_t>& dst_skip, + const std::vector<uint8_t>& copy_count); + + EquivalenceSink(EquivalenceSink&&); + ~EquivalenceSink(); + + // Core functions. + // Equivalences must be given by increasing |Equivalence::dst_offset|. + void PutNext(const Equivalence& equivalence); + size_t SerializedSize() const; + bool SerializeInto(BufferSink* sink) const; + + private: + // Offset in source, delta-encoded starting from end of last equivalence, and + // stored as signed varint. + std::vector<uint8_t> src_skip_; + // Offset in destination, delta-encoded starting from end of last equivalence, + // and stored as unsigned varint. + std::vector<uint8_t> dst_skip_; + // Length of equivalence stored as unsigned varint. + // TODO(etiennep): Investigate on bias. + std::vector<uint8_t> copy_count_; + + offset_t src_offset_ = 0; // Last offset in source. + offset_t dst_offset_ = 0; // Last offset in destination. +}; + +// Sink for extra data. +class ExtraDataSink { + public: + ExtraDataSink(); + explicit ExtraDataSink(const std::vector<uint8_t>& extra_data); + ExtraDataSink(ExtraDataSink&&); + ~ExtraDataSink(); + + // Core functions. + void PutNext(ConstBufferView region); + size_t SerializedSize() const; + bool SerializeInto(BufferSink* sink) const; + + private: + std::vector<uint8_t> extra_data_; +}; + +// Sink for raw delta. +class RawDeltaSink { + public: + RawDeltaSink(); + RawDeltaSink(const std::vector<uint8_t>& raw_delta_skip, + const std::vector<uint8_t>& raw_delta_diff); + RawDeltaSink(RawDeltaSink&&); + ~RawDeltaSink(); + + // Core functions. + // Deltas must be given by increasing |RawDeltaUnit::copy_offset|. + void PutNext(const RawDeltaUnit& delta); + size_t SerializedSize() const; + bool SerializeInto(BufferSink* sink) const; + + private: + std::vector<uint8_t> raw_delta_skip_; // Copy offset stating from last delta. + std::vector<uint8_t> raw_delta_diff_; // Bytewise difference. + + // We keep track of the compensation needed for next copy offset, taking into + // accound delta encoding and bias of -1. Stored delta are biased by -1, so a + // sequence of single byte deltas is represented as a string of 0's. + offset_t copy_offset_compensation_ = 0; +}; + +// Sink for reference delta. +class ReferenceDeltaSink { + public: + ReferenceDeltaSink(); + explicit ReferenceDeltaSink(const std::vector<uint8_t>& reference_delta); + ReferenceDeltaSink(ReferenceDeltaSink&&); + ~ReferenceDeltaSink(); + + // Core functions. + void PutNext(int32_t diff); + size_t SerializedSize() const; + bool SerializeInto(BufferSink* sink) const; + + private: + std::vector<uint8_t> reference_delta_; +}; + +// Sink for additional targets. +class TargetSink { + public: + TargetSink(); + explicit TargetSink(const std::vector<uint8_t>& extra_targets); + TargetSink(TargetSink&&); + ~TargetSink(); + + // Core functions. + // Targets must be given by increasing order. + void PutNext(uint32_t target); + size_t SerializedSize() const; + bool SerializeInto(BufferSink* sink) const; + + private: + // Targets are delta-encoded and biaised by 1, stored as unsigned varint. + std::vector<uint8_t> extra_targets_; + + // We keep track of the compensation needed for next target, taking into + // accound delta encoding and bias of -1. + offset_t target_compensation_ = 0; +}; + +// Following are utility classes to write structured data forming a patch. + +// Utility to write a patch element. A patch element contains all the +// information necessary to patch a single element. This class +// provides an interface to individually set different building blocks of data +// in the patch element. +class PatchElementWriter { + public: + PatchElementWriter(); + explicit PatchElementWriter(ElementMatch element_match); + PatchElementWriter(PatchElementWriter&&); + ~PatchElementWriter(); + + const ElementMatch& element_match() const { return element_match_; } + const Element& old_element() const { return element_match_.old_element; } + const Element& new_element() const { return element_match_.new_element; } + + // Following methods set individual blocks for this element. Previous + // corresponding block is replaced. All streams must be set before call to + // SerializedSize() of SerializeInto(). + + void SetEquivalenceSink(EquivalenceSink&& equivalences) { + equivalences_.emplace(std::move(equivalences)); + } + void SetExtraDataSink(ExtraDataSink&& extra_data) { + extra_data_.emplace(std::move(extra_data)); + } + void SetRawDeltaSink(RawDeltaSink&& raw_delta) { + raw_delta_.emplace(std::move(raw_delta)); + } + void SetReferenceDeltaSink(ReferenceDeltaSink reference_delta) { + reference_delta_.emplace(std::move(reference_delta)); + } + // Set additional targets for pool identified with |pool_tag|. + void SetTargetSink(PoolTag pool_tag, TargetSink&& extra_targets) { + DCHECK(pool_tag != kNoPoolTag); + extra_targets_.emplace(pool_tag, std::move(extra_targets)); + } + + // Returns the serialized size in bytes of the data this object is holding. + size_t SerializedSize() const; + + // If sufficient space is available, serializes data into |sink|, which is at + // least SerializedSize() bytes, and returns true. Otherwise returns false. + bool SerializeInto(BufferSink* sink) const; + + private: + ElementMatch element_match_; + base::Optional<EquivalenceSink> equivalences_; + base::Optional<ExtraDataSink> extra_data_; + base::Optional<RawDeltaSink> raw_delta_; + base::Optional<ReferenceDeltaSink> reference_delta_; + std::map<PoolTag, TargetSink> extra_targets_; +}; + +// Utility to write a Zucchini ensemble patch. An ensemble patch is the +// concatenation of a patch header with a vector of patch elements. +class EnsemblePatchWriter { + public: + explicit EnsemblePatchWriter(const PatchHeader& header); + EnsemblePatchWriter(ConstBufferView old_image, ConstBufferView new_image); + ~EnsemblePatchWriter(); + + void SetPatchType(PatchType patch_type) { patch_type_ = patch_type; } + + // Reserves space for |count| patch elements. + void ReserveElements(size_t count) { elements_.reserve(count); } + + // Adds an patch element into the patch. Patch elements must be ordered by + // their location in the new image file. + void AddElement(PatchElementWriter&& patch_element); + + // Returns the serialized size in bytes of the data this object is holding. + size_t SerializedSize() const; + + // If sufficient space is available, serializes data into |sink|, which is at + // least SerializedSize() bytes, and returns true. Otherwise returns false. + bool SerializeInto(BufferSink* sink) const; + + // If sufficient space is available, serializes data into |buffer|, which is + // at least SerializedSize() bytes, and returns true. Otherwise returns false. + bool SerializeInto(MutableBufferView buffer) const { + BufferSink sink(buffer); + return SerializeInto(&sink); + } + + private: + PatchHeader header_; + PatchType patch_type_ = PatchType::kUnrecognisedPatch; + std::vector<PatchElementWriter> elements_; + offset_t current_dst_offset_ = 0; + + DISALLOW_COPY_AND_ASSIGN(EnsemblePatchWriter); +}; + +} // namespace zucchini + +#endif // CHROME_INSTALLER_ZUCCHINI_PATCH_WRITER_H_
diff --git a/chrome/test/data/extensions/bookmark_apps/url_handlers/in_scope/other.html b/chrome/test/data/extensions/bookmark_apps/url_handlers/in_scope/other.html deleted file mode 100644 index e69de29..0000000 --- a/chrome/test/data/extensions/bookmark_apps/url_handlers/in_scope/other.html +++ /dev/null
diff --git a/chrome/test/data/extensions/bookmark_apps/url_handlers/out_of_scope/other.html b/chrome/test/data/extensions/bookmark_apps/url_handlers/out_of_scope/other.html deleted file mode 100644 index e69de29..0000000 --- a/chrome/test/data/extensions/bookmark_apps/url_handlers/out_of_scope/other.html +++ /dev/null
diff --git a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java index 8af04241..5d78b99 100644 --- a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java +++ b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java
@@ -76,6 +76,12 @@ private static final int AUDIO_MODE = AudioTrack.MODE_STREAM; private static final int BYTES_PER_FRAME = 2 * 4; // 2 channels, float (4-bytes) + // Parameter to determine the proper internal buffer size of the AudioTrack instance. In order + // to minimize latency we want a buffer as small as possible. However, to avoid underruns we + // need a size several times the size returned by AudioTrack.getMinBufferSize() (see + // the Android documentation for details). + private static final int MIN_BUFFER_SIZE_MULTIPLIER = 3; + private static final long NO_TIMESTAMP = Long.MIN_VALUE; private static final long SEC_IN_NSEC = 1000000000L; @@ -198,18 +204,16 @@ } mSampleRateInHz = sampleRateInHz; - // TODO(ckuiper): ALSA code uses a 90ms buffer size, we should do something - // similar. - int bufferSizeInBytes = - 5 * AudioTrack.getMinBufferSize(mSampleRateInHz, CHANNEL_CONFIG, AUDIO_FORMAT); - int usageType = CAST_TYPE_TO_ANDROID_USAGE_TYPE_MAP.get(castContentType); int contentType = CAST_TYPE_TO_ANDROID_CONTENT_TYPE_MAP.get(castContentType); int sessionId = (usageType == AudioAttributes.USAGE_MEDIA) ? getSessionIdMedia() : getSessionIdNonMedia(); + int bufferSizeInBytes = MIN_BUFFER_SIZE_MULTIPLIER + * AudioTrack.getMinBufferSize(mSampleRateInHz, CHANNEL_CONFIG, AUDIO_FORMAT); + int bufferSizeInMs = 1000 * bufferSizeInBytes / (BYTES_PER_FRAME * mSampleRateInHz); Log.i(TAG, - "Init: create an AudioTrack of size=" + bufferSizeInBytes - + " usageType=" + usageType + " contentType=" + contentType + "Init: create an AudioTrack of size=" + bufferSizeInBytes + " (" + bufferSizeInMs + + "ms) usageType=" + usageType + " contentType=" + contentType + " with session-id=" + sessionId); AudioTrack.Builder builder = new AudioTrack.Builder();
diff --git a/chromeos/timezone/timezone_resolver.cc b/chromeos/timezone/timezone_resolver.cc index 68795f8..11b0f3c 100644 --- a/chromeos/timezone/timezone_resolver.cc +++ b/chromeos/timezone/timezone_resolver.cc
@@ -226,7 +226,7 @@ base::Bind(&TZRequest::OnTimezoneResolved, AsWeakPtr())); // Prevent |on_request_finished| from firing here. - base::Closure unused = on_request_finished.Release(); + base::OnceClosure unused = on_request_finished.Release(); } void TZRequest::OnTimezoneResolved(
diff --git a/components/drive/chromeos/file_system/download_operation.cc b/components/drive/chromeos/file_system/download_operation.cc index 4e8d01d..e38ca4a 100644 --- a/components/drive/chromeos/file_system/download_operation.cc +++ b/components/drive/chromeos/file_system/download_operation.cc
@@ -250,7 +250,7 @@ internal::FileCache::FILE_OPERATION_MOVE); if (error != FILE_ERROR_OK) return error; - base::Closure unused_file_deleter_closure = file_deleter.Release(); + base::OnceClosure unused_file_deleter_closure = file_deleter.Release(); error = metadata->GetResourceEntryById(local_id, entry_after_update); if (error != FILE_ERROR_OK)
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc index df91ada4..481338a 100644 --- a/components/exo/shell_surface.cc +++ b/components/exo/shell_surface.cc
@@ -57,15 +57,24 @@ // Fix it on Android side and reduce the timeout. constexpr int kRotationLockTimeoutMs = 2500; -// This is a struct for accelerator keys used to close ShellSurfaces. -const struct Accelerator { +// This is a struct for accelerator keys. +struct Accelerator { ui::KeyboardCode keycode; int modifiers; -} kCloseWindowAccelerators[] = { +}; + +// The accelerator keys used to close ShellSurfaces. +const Accelerator kCloseWindowAccelerators[] = { {ui::VKEY_W, ui::EF_CONTROL_DOWN}, {ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}, {ui::VKEY_F4, ui::EF_ALT_DOWN}}; +// The accelerator keys reserved to be processed by the focus manager. +const Accelerator kReservedAccelerators[] = { + {ui::VKEY_SPACE, ui::EF_CONTROL_DOWN}, + {ui::VKEY_SPACE, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}, + {ui::VKEY_F13, ui::EF_NONE}}; + class CustomFrameView : public views::NonClientFrameView { public: explicit CustomFrameView(views::Widget* widget) : widget_(widget) {} @@ -195,6 +204,16 @@ void OnKeyEvent(ui::KeyEvent* event) override { // TODO(hidehiko): Handle ESC + SHIFT + COMMAND accelerator key // to escape pinned mode. + for (const auto& entry : kReservedAccelerators) { + // Handle only reserved accelerators. + if (event->flags() == entry.modifiers && + event->key_code() == entry.keycode) { + if (GetFocusManager()->ProcessAccelerator(ui::Accelerator(*event))) + event->StopPropagation(); + } + } + // Do not call Widget::OnKeyEvent that eats focus management keys (like the + // tab key) as well. } private:
diff --git a/components/prefs/pref_member.cc b/components/prefs/pref_member.cc index f0be267..6907f66 100644 --- a/components/prefs/pref_member.cc +++ b/components/prefs/pref_member.cc
@@ -102,13 +102,12 @@ return thread_task_runner_->BelongsToCurrentThread(); } -void PrefMemberBase::Internal::UpdateValue( - base::Value* v, - bool is_managed, - bool is_user_modifiable, - const base::Closure& callback) const { +void PrefMemberBase::Internal::UpdateValue(base::Value* v, + bool is_managed, + bool is_user_modifiable, + base::OnceClosure callback) const { std::unique_ptr<base::Value> value(v); - base::ScopedClosureRunner closure_runner(callback); + base::ScopedClosureRunner closure_runner(std::move(callback)); if (IsOnCorrectThread()) { bool rv = UpdateValueInternal(*value); DCHECK(rv); @@ -116,9 +115,10 @@ is_user_modifiable_ = is_user_modifiable; } else { bool may_run = thread_task_runner_->PostTask( - FROM_HERE, base::Bind(&PrefMemberBase::Internal::UpdateValue, this, - value.release(), is_managed, is_user_modifiable, - closure_runner.Release())); + FROM_HERE, + base::BindOnce(&PrefMemberBase::Internal::UpdateValue, this, + value.release(), is_managed, is_user_modifiable, + closure_runner.Release())); DCHECK(may_run); } }
diff --git a/components/prefs/pref_member.h b/components/prefs/pref_member.h index f46e3686..205f432 100644 --- a/components/prefs/pref_member.h +++ b/components/prefs/pref_member.h
@@ -63,7 +63,7 @@ void UpdateValue(base::Value* value, bool is_managed, bool is_user_modifiable, - const base::Closure& callback) const; + base::OnceClosure callback) const; void MoveToThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner);
diff --git a/components/safe_browsing/features.cc b/components/safe_browsing/features.cc index 99ba220f..560dbc6 100644 --- a/components/safe_browsing/features.cc +++ b/components/safe_browsing/features.cc
@@ -31,13 +31,13 @@ base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kPasswordFieldOnFocusPinging{ - "PasswordFieldOnFocusPinging", base::FEATURE_DISABLED_BY_DEFAULT}; + "PasswordFieldOnFocusPinging", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kPasswordProtectionInterstitial{ "PasswordProtectionInterstitial", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kProtectedPasswordEntryPinging{ - "ProtectedPasswordEntryPinging", base::FEATURE_DISABLED_BY_DEFAULT}; + "ProtectedPasswordEntryPinging", base::FEATURE_ENABLED_BY_DEFAULT}; // Specifies which non-resource HTML Elements to collect based on their tag and // attributes. It's a single param containing a comma-separated list of pairs.
diff --git a/components/safe_browsing/web_ui/resources/safe_browsing.html b/components/safe_browsing/web_ui/resources/safe_browsing.html index 0ee0ccf..fe60658 100644 --- a/components/safe_browsing/web_ui/resources/safe_browsing.html +++ b/components/safe_browsing/web_ui/resources/safe_browsing.html
@@ -28,6 +28,10 @@ <div class="content"> <p id="database-info-list"></p> </div> + <h2>Full Hash Cache</h2> + <div class="content"> + <p id="full-hash-cache-info"></p> + </div> <script src="chrome://resources/js/i18n_template.js"></script> </body> </html>
diff --git a/components/safe_browsing/web_ui/resources/safe_browsing.js b/components/safe_browsing/web_ui/resources/safe_browsing.js index d6be52b4..8c203f7 100644 --- a/components/safe_browsing/web_ui/resources/safe_browsing.js +++ b/components/safe_browsing/web_ui/resources/safe_browsing.js
@@ -15,9 +15,12 @@ addExperiments(experiments)); cr.sendWithPromise('getPrefs', []).then((prefs) => addPrefs(prefs)); cr.sendWithPromise('getDatabaseManagerInfo', []).then( - (databaseState) => addDatabaseManagerInfo(databaseState)); - } - + function(databaseState) { + var fullHashCacheState = databaseState.splice(-1,1); + addDatabaseManagerInfo(databaseState); + addFullHashCacheInfo(fullHashCacheState); + }); +} function addExperiments(result) { var resLength = result.length; var experimentsListFormatted = ""; @@ -40,7 +43,6 @@ $('preferences-list').innerHTML = preferencesListFormatted; } - function addDatabaseManagerInfo(result) { var resLength = result.length; var preferencesListFormatted = ""; @@ -52,6 +54,10 @@ $('database-info-list').innerHTML = preferencesListFormatted; } + function addFullHashCacheInfo(result) { + $('full-hash-cache-info').innerHTML = result; + } + return { initialize: initialize, };
diff --git a/components/safe_browsing/web_ui/safe_browsing_ui.cc b/components/safe_browsing/web_ui/safe_browsing_ui.cc index 547222e0..fd62c90 100644 --- a/components/safe_browsing/web_ui/safe_browsing_ui.cc +++ b/components/safe_browsing/web_ui/safe_browsing_ui.cc
@@ -9,7 +9,9 @@ #include <utility> #include <vector> +#include "base/base64url.h" #include "base/i18n/time_formatting.h" +#include "base/json/json_string_value_serializer.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "base/values.h" @@ -97,6 +99,101 @@ update_info.last_update_time_millis())); } } + +void ParseFullHashInfo( + const FullHashCacheInfo::FullHashCache::CachedHashPrefixInfo::FullHashInfo + full_hash_info, + base::DictionaryValue* full_hash_info_dict) { + if (full_hash_info.has_positive_expiry()) { + full_hash_info_dict->SetString( + "Positivie expiry", + UserReadableTimeFromMillisSinceEpoch(full_hash_info.positive_expiry()) + .GetString()); + } + if (full_hash_info.has_full_hash()) { + std::string full_hash; + base::Base64UrlEncode(full_hash_info.full_hash(), + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &full_hash); + full_hash_info_dict->SetString("Full hash (base64)", full_hash); + } + if (full_hash_info.list_identifier().has_platform_type()) { + full_hash_info_dict->SetInteger( + "platform_type", full_hash_info.list_identifier().platform_type()); + } + if (full_hash_info.list_identifier().has_threat_entry_type()) { + full_hash_info_dict->SetInteger( + "threat_entry_type", + full_hash_info.list_identifier().threat_entry_type()); + } + if (full_hash_info.list_identifier().has_threat_type()) { + full_hash_info_dict->SetInteger( + "threat_type", full_hash_info.list_identifier().threat_type()); + } +} + +void ParseFullHashCache(const FullHashCacheInfo::FullHashCache full_hash_cache, + base::ListValue* full_hash_cache_list) { + base::DictionaryValue full_hash_cache_parsed; + + if (full_hash_cache.has_hash_prefix()) { + std::string hash_prefix; + base::Base64UrlEncode(full_hash_cache.hash_prefix(), + base::Base64UrlEncodePolicy::INCLUDE_PADDING, + &hash_prefix); + full_hash_cache_parsed.SetString("Hash prefix (base64)", hash_prefix); + } + if (full_hash_cache.cached_hash_prefix_info().has_negative_expiry()) { + full_hash_cache_parsed.SetString( + "Negative expiry", + UserReadableTimeFromMillisSinceEpoch( + full_hash_cache.cached_hash_prefix_info().negative_expiry()) + .GetString()); + } + + full_hash_cache_list->GetList().push_back(full_hash_cache_parsed); + + for (auto full_hash_info_it : + full_hash_cache.cached_hash_prefix_info().full_hash_info()) { + base::DictionaryValue full_hash_info_dict; + ParseFullHashInfo(full_hash_info_it, &full_hash_info_dict); + full_hash_cache_list->GetList().push_back(full_hash_info_dict); + } +} + +void ParseFullHashCacheInfo(const FullHashCacheInfo full_hash_cache_info_proto, + base::ListValue* full_hash_cache_info) { + if (full_hash_cache_info_proto.has_number_of_hits()) { + base::DictionaryValue number_of_hits; + number_of_hits.SetInteger("Number of cache hits", + full_hash_cache_info_proto.number_of_hits()); + full_hash_cache_info->GetList().push_back(number_of_hits); + } + + // Record FullHashCache list. + for (auto full_hash_cache_it : full_hash_cache_info_proto.full_hash_cache()) { + base::ListValue full_hash_cache_list; + ParseFullHashCache(full_hash_cache_it, &full_hash_cache_list); + full_hash_cache_info->GetList().push_back(full_hash_cache_list); + } +} + +std::string AddFullHashCacheInfo( + const FullHashCacheInfo full_hash_cache_info_proto) { + std::string full_hash_cache_parsed; + + base::ListValue full_hash_cache; + ParseFullHashCacheInfo(full_hash_cache_info_proto, &full_hash_cache); + + base::Value* full_hash_cache_tree = &full_hash_cache; + + JSONStringValueSerializer serializer(&full_hash_cache_parsed); + serializer.set_pretty_print(true); + serializer.Serialize(*full_hash_cache_tree); + + return full_hash_cache_parsed; +} + #endif } // namespace @@ -158,12 +255,12 @@ #if SAFE_BROWSING_DB_LOCAL const V4LocalDatabaseManager* local_database_manager_instance = V4LocalDatabaseManager::current_local_database_manager(); - if (local_database_manager_instance) { DatabaseManagerInfo database_manager_info_proto; + FullHashCacheInfo full_hash_cache_info_proto; local_database_manager_instance->CollectDatabaseManagerInfo( - &database_manager_info_proto); + &database_manager_info_proto, &full_hash_cache_info_proto); if (database_manager_info_proto.has_update_info()) { AddUpdateInfo(database_manager_info_proto.update_info(), @@ -173,6 +270,9 @@ AddDatabaseInfo(database_manager_info_proto.database_info(), &database_manager_info); } + + database_manager_info.GetList().push_back( + base::Value(AddFullHashCacheInfo(full_hash_cache_info_proto))); } #endif
diff --git a/components/safe_browsing/web_ui/webui.proto b/components/safe_browsing/web_ui/webui.proto index bc0e96e7..c495460 100644 --- a/components/safe_browsing/web_ui/webui.proto +++ b/components/safe_browsing/web_ui/webui.proto
@@ -58,3 +58,49 @@ optional DatabaseInfo database_info = 2; } + +// The information about the list of prefixes for which the full hashes have +// been stored in the cache. +message FullHashCacheInfo { + // Records number of cache hits since the beginning of the session. + optional int32 number_of_hits = 1; + // Cached full hashes received from the server for the corresponding hash + // prefixes. + message FullHashCache { + // The hash prefix for which the full hashes are stored in the cache. + optional string hash_prefix = 1; + // The information about a hash prefix stored in the cache. + message CachedHashPrefixInfo { + // The negative ttl for the hash prefix. + optional int64 negative_expiry = 1; + // The information about a particular full hash. + message FullHashInfo { + // The expiration time of the full hash for a particular store. + optional int64 positive_expiry = 1; + // A variable-length SHA256 hash with size between 4 and 32 bytes + // inclusive. + optional string full_hash = 2; + // The list for which this full hash is applicable. + message ListIdentifier { + // Types of platforms. The value of platform_type corresponds to the + // PlatformType enum in safebrowsing_proto. + optional int32 platform_type = 1; + // Types of entries that pose threats. The value of threat_entry_type + // corresponds to the ThreatEntryType enum in safebrowsing_proto. + optional int32 threat_entry_type = 2; + // Types of threats. The value of threat_type corresponds to the + // ThreatType enum in safebrowsing_proto. + optional int32 threat_type = 3; + } + optional ListIdentifier list_identifier = 3; + } + // The list of all full hashes (and related info) that start with a + // particular hash prefix and are known to be unsafe. + repeated FullHashInfo full_hash_info = 2; + } + // Information about the cached hash prefix for each hash prefix in the + // cache. + optional CachedHashPrefixInfo cached_hash_prefix_info = 2; + } + repeated FullHashCache full_hash_cache = 2; +}
diff --git a/components/safe_browsing_db/BUILD.gn b/components/safe_browsing_db/BUILD.gn index 4ccc808..bedfc8e 100644 --- a/components/safe_browsing_db/BUILD.gn +++ b/components/safe_browsing_db/BUILD.gn
@@ -233,6 +233,7 @@ ":v4_protocol_manager_util", "//base", "//components/data_use_measurement/core", + "//components/safe_browsing/web_ui:webui_proto", "//content/public/browser", "//net", "//url",
diff --git a/components/safe_browsing_db/v4_get_hash_protocol_manager.cc b/components/safe_browsing_db/v4_get_hash_protocol_manager.cc index a0878d15..31bd519 100644 --- a/components/safe_browsing_db/v4_get_hash_protocol_manager.cc +++ b/components/safe_browsing_db/v4_get_hash_protocol_manager.cc
@@ -381,7 +381,7 @@ full_hash_to_store_and_hash_prefixes, const Time& now, std::vector<HashPrefix>* prefixes_to_request, - std::vector<FullHashInfo>* cached_full_hash_infos) const { + std::vector<FullHashInfo>* cached_full_hash_infos) { DCHECK(!full_hash_to_store_and_hash_prefixes.empty()); DCHECK(prefixes_to_request->empty()); DCHECK(cached_full_hash_infos->empty()); @@ -433,6 +433,7 @@ full_hash_info.list_id == list_id) { // Case a. found_full_hash = true; + number_of_hits_++; if (full_hash_info.positive_expiry > now) { // Case i. cached_full_hash_infos->push_back(full_hash_info); @@ -788,6 +789,35 @@ pending_hash_requests_.erase(it); } +void V4GetHashProtocolManager::CollectFullHashCacheInfo( + FullHashCacheInfo* full_hash_cache_info) { + full_hash_cache_info->set_number_of_hits(number_of_hits_); + + for (const auto& it : full_hash_cache_) { + FullHashCacheInfo::FullHashCache* full_hash_cache = + full_hash_cache_info->add_full_hash_cache(); + full_hash_cache->set_hash_prefix(it.first); + full_hash_cache->mutable_cached_hash_prefix_info()->set_negative_expiry( + it.second.negative_expiry.ToJavaTime()); + + for (const auto& full_hash_infos_it : it.second.full_hash_infos) { + FullHashCacheInfo::FullHashCache::CachedHashPrefixInfo::FullHashInfo* + full_hash_info = full_hash_cache->mutable_cached_hash_prefix_info() + ->add_full_hash_info(); + full_hash_info->set_positive_expiry( + full_hash_infos_it.positive_expiry.ToJavaTime()); + full_hash_info->set_full_hash(full_hash_infos_it.full_hash); + + full_hash_info->mutable_list_identifier()->set_platform_type( + static_cast<int>(full_hash_infos_it.list_id.platform_type())); + full_hash_info->mutable_list_identifier()->set_threat_entry_type( + static_cast<int>(full_hash_infos_it.list_id.threat_entry_type())); + full_hash_info->mutable_list_identifier()->set_threat_type( + static_cast<int>(full_hash_infos_it.list_id.threat_type())); + } + } +} + #ifndef DEBUG std::ostream& operator<<(std::ostream& os, const FullHashInfo& fhi) { os << "{full_hash: " << fhi.full_hash << "; list_id: " << fhi.list_id
diff --git a/components/safe_browsing_db/v4_get_hash_protocol_manager.h b/components/safe_browsing_db/v4_get_hash_protocol_manager.h index 6e43e88..6ae5c302 100644 --- a/components/safe_browsing_db/v4_get_hash_protocol_manager.h +++ b/components/safe_browsing_db/v4_get_hash_protocol_manager.h
@@ -24,6 +24,7 @@ #include "base/time/default_clock.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "components/safe_browsing/web_ui/webui.pb.h" #include "components/safe_browsing_db/safebrowsing.pb.h" #include "components/safe_browsing_db/util.h" #include "components/safe_browsing_db/v4_protocol_manager_util.h" @@ -187,6 +188,9 @@ // net::URLFetcherDelegate interface. void OnURLFetchComplete(const net::URLFetcher* source) override; + // Populates the protobuf with the FullHashCache data. + void CollectFullHashCacheInfo(FullHashCacheInfo* full_hash_cache_info); + protected: // Constructs a V4GetHashProtocolManager that issues network requests using // |request_context_getter|. @@ -231,7 +235,7 @@ full_hash_to_store_and_hash_prefixes, const base::Time& now, std::vector<HashPrefix>* prefixes_to_request, - std::vector<FullHashInfo>* cached_full_hash_infos) const; + std::vector<FullHashInfo>* cached_full_hash_infos); // Fills a FindFullHashesRequest protocol buffer for a request. // Returns the serialized and base 64 encoded request as a string. @@ -327,6 +331,9 @@ // The context we use to issue network requests. scoped_refptr<net::URLRequestContextGetter> request_context_getter_; + // Records number of cache hits since the beginning of this session. + int number_of_hits_ = 0; + // ID for URLFetchers for testing. int url_fetcher_id_;
diff --git a/components/safe_browsing_db/v4_local_database_manager.cc b/components/safe_browsing_db/v4_local_database_manager.cc index abca3e7..d0eb1dd 100644 --- a/components/safe_browsing_db/v4_local_database_manager.cc +++ b/components/safe_browsing_db/v4_local_database_manager.cc
@@ -17,7 +17,6 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/task_scheduler/post_task.h" -#include "components/safe_browsing/web_ui/webui.pb.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_thread.h" @@ -186,13 +185,20 @@ } void V4LocalDatabaseManager::CollectDatabaseManagerInfo( - DatabaseManagerInfo* database_manager_info) const { - v4_update_protocol_manager_->CollectUpdateInfo( - database_manager_info->mutable_update_info()); - - // Update the protobuf with the information from V4Database. - v4_database_->CollectDatabaseInfo( - database_manager_info->mutable_database_info()); + DatabaseManagerInfo* database_manager_info, + FullHashCacheInfo* full_hash_cache_info) const { + if (v4_update_protocol_manager_) { + v4_update_protocol_manager_->CollectUpdateInfo( + database_manager_info->mutable_update_info()); + } + if (v4_database_) { + v4_database_->CollectDatabaseInfo( + database_manager_info->mutable_database_info()); + } + if (v4_get_hash_protocol_manager_) { + v4_get_hash_protocol_manager_->CollectFullHashCacheInfo( + full_hash_cache_info); + } } V4LocalDatabaseManager::V4LocalDatabaseManager(
diff --git a/components/safe_browsing_db/v4_local_database_manager.h b/components/safe_browsing_db/v4_local_database_manager.h index e81ff3d9..29d7544 100644 --- a/components/safe_browsing_db/v4_local_database_manager.h +++ b/components/safe_browsing_db/v4_local_database_manager.h
@@ -36,7 +36,10 @@ ExtendedReportingLevelCallback extended_reporting_level_callback); // Populates the protobuf with the database data. - void CollectDatabaseManagerInfo(DatabaseManagerInfo* v4_database_info) const; + void CollectDatabaseManagerInfo( + DatabaseManagerInfo* v4_database_info, + FullHashCacheInfo* full_hash_cache_info) const; + // Return an instance of the V4LocalDatabaseManager object static const V4LocalDatabaseManager* current_local_database_manager() { return current_local_database_manager_;
diff --git a/components/safe_browsing_db/v4_update_protocol_manager.cc b/components/safe_browsing_db/v4_update_protocol_manager.cc index 1be6820..fbefa54 100644 --- a/components/safe_browsing_db/v4_update_protocol_manager.cc +++ b/components/safe_browsing_db/v4_update_protocol_manager.cc
@@ -13,7 +13,6 @@ #include "base/rand_util.h" #include "base/timer/timer.h" #include "components/data_use_measurement/core/data_use_user_data.h" -#include "components/safe_browsing/web_ui/webui.pb.h" #include "components/safe_browsing_db/safebrowsing.pb.h" #include "net/base/load_flags.h" #include "net/http/http_response_headers.h"
diff --git a/components/test/data/payments/no_shipping.js b/components/test/data/payments/no_shipping.js index a87473b..8d70f52 100644 --- a/components/test/data/payments/no_shipping.js +++ b/components/test/data/payments/no_shipping.js
@@ -26,9 +26,7 @@ .then(function(resp) { resp.complete('success') .then(function() { - print( - resp.methodName + '<br>' + - JSON.stringify(resp.details, undefined, 2)); + print(JSON.stringify(resp, undefined, 2)); }) .catch(function(error) { print(error);
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index 8779ab4..9a526397 100644 --- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -35,6 +35,7 @@ #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/ssl_status.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" @@ -1970,4 +1971,65 @@ EXPECT_EQ(2u, found); } +class DevToolsProtocolTouchTest : public DevToolsProtocolTest { + public: + ~DevToolsProtocolTouchTest() override {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitchASCII( + switches::kTouchEventFeatureDetection, + switches::kTouchEventFeatureDetectionDisabled); + } +}; + +IN_PROC_BROWSER_TEST_F(DevToolsProtocolTouchTest, EnableTouch) { + std::unique_ptr<base::DictionaryValue> params; + bool result; + + ASSERT_TRUE(embedded_test_server()->Start()); + GURL test_url = embedded_test_server()->GetURL("/devtools/enable_touch.html"); + NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1); + Attach(); + + params.reset(new base::DictionaryValue()); + SendCommand("Page.enable", std::move(params), true); + + ASSERT_TRUE(content::ExecuteScriptAndExtractBool( + shell()->web_contents(), + "domAutomationController.send(checkProtos(false))", &result)); + EXPECT_TRUE(result); + + params.reset(new base::DictionaryValue()); + params->SetBoolean("enabled", true); + SendCommand("Emulation.setTouchEmulationEnabled", std::move(params), true); + ASSERT_TRUE(content::ExecuteScriptAndExtractBool( + shell()->web_contents(), + "domAutomationController.send(checkProtos(false))", &result)); + EXPECT_TRUE(result); + + params.reset(new base::DictionaryValue()); + SendCommand("Page.reload", std::move(params), false); + WaitForNotification("Page.frameStoppedLoading"); + ASSERT_TRUE(content::ExecuteScriptAndExtractBool( + shell()->web_contents(), + "domAutomationController.send(checkProtos(true))", &result)); + EXPECT_TRUE(result); + + params.reset(new base::DictionaryValue()); + params->SetBoolean("enabled", false); + SendCommand("Emulation.setTouchEmulationEnabled", std::move(params), true); + ASSERT_TRUE(content::ExecuteScriptAndExtractBool( + shell()->web_contents(), + "domAutomationController.send(checkProtos(true))", &result)); + EXPECT_TRUE(result); + + params.reset(new base::DictionaryValue()); + SendCommand("Page.reload", std::move(params), false); + WaitForNotification("Page.frameStoppedLoading"); + ASSERT_TRUE(content::ExecuteScriptAndExtractBool( + shell()->web_contents(), + "domAutomationController.send(checkProtos(false))", &result)); + EXPECT_TRUE(result); +} + } // namespace content
diff --git a/content/browser/loader/resource_scheduler.cc b/content/browser/loader/resource_scheduler.cc index a442f14..356b90a 100644 --- a/content/browser/loader/resource_scheduler.cc +++ b/content/browser/loader/resource_scheduler.cc
@@ -9,7 +9,6 @@ #include <string> #include <utility> -#include "base/feature_list.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/metrics/field_trial.h" @@ -64,6 +63,14 @@ const base::Feature kMaxDelayableRequestsNetworkOverride{ "MaxDelayableRequestsNetworkOverride", base::FEATURE_DISABLED_BY_DEFAULT}; +// This experiment throttles delayable requests based on the number of +// non-delayable requests in-flight times a weighting factor. The experiment is +// enabled only when the effective connection type is strictly greater than +// net::EFFECTIVE_CONNECTION_TYPE_OFFLINE and less than or equal to +// the maximum effective connection type in the configuration. +const base::Feature kNonDelayableThrottlesDelayable{ + "NonDelayableThrottlesDelayable", base::FEATURE_DISABLED_BY_DEFAULT}; + enum StartMode { START_SYNC, START_ASYNC @@ -732,6 +739,13 @@ net::NetLog::StringCallback( "trigger", RequestStartTriggerString(trigger))); } + // Record the number of delayable requests in-flight when a non-delayable + // request starts. + if (!RequestAttributesAreSet(request->attributes(), kAttributeDelayable)) { + UMA_HISTOGRAM_COUNTS_100( + "ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable", + in_flight_delayable_count_); + } InsertInFlightRequest(request); request->Start(start_mode); } @@ -806,8 +820,15 @@ return ShouldStartOrYieldRequest(); // Delayable requests. - if (in_flight_delayable_count_ >= max_delayable_requests_) + DCHECK_GE(in_flight_requests_.size(), in_flight_delayable_count_); + size_t num_non_delayable_requests_weighted = static_cast<size_t>( + resource_scheduler_->non_delayable_throttles_delayable_experiment_ + .GetCurrentNonDelayableWeight(network_quality_estimator_) * + (in_flight_requests_.size() - in_flight_delayable_count_)); + if (in_flight_delayable_count_ + num_non_delayable_requests_weighted >= + max_delayable_requests_) { return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; + } if (ShouldKeepSearching(host_port_pair)) { // There may be other requests for other hosts that may be allowed, @@ -1271,4 +1292,35 @@ } } +ResourceScheduler::NonDelayableThrottlesDelayableExperiment:: + NonDelayableThrottlesDelayableExperiment() + : max_effective_connection_type_(GetEffectiveConnectionTypeForNameWrapper( + base::GetFieldTrialParamValueByFeature( + kNonDelayableThrottlesDelayable, + "MaxEffectiveConnectionType"))), + non_delayable_weight_(base::GetFieldTrialParamByFeatureAsDouble( + kNonDelayableThrottlesDelayable, + "NonDelayableWeight", + 0.0)) {} + +double ResourceScheduler::NonDelayableThrottlesDelayableExperiment:: + GetCurrentNonDelayableWeight( + const net::NetworkQualityEstimator* network_quality_estimator) const { + if (!network_quality_estimator) { + // Fall back to default behavior by setting the weight of non-delayable + // requests to 0 when |network_quality_estimator| is not set. + return 0.0; + } + net::EffectiveConnectionType effective_connection_type = + network_quality_estimator->GetEffectiveConnectionType(); + if (effective_connection_type > max_effective_connection_type_ || + effective_connection_type <= net::EFFECTIVE_CONNECTION_TYPE_OFFLINE) { + // If the effective connection type is detected as offline or unknown, or + // strictly better than the maximum effective connection type set in the + // experiment parameters, fall back to the default behavior. + return 0.0; + } + return non_delayable_weight_; +} + } // namespace content
diff --git a/content/browser/loader/resource_scheduler.h b/content/browser/loader/resource_scheduler.h index 76329eb..70b25de 100644 --- a/content/browser/loader/resource_scheduler.h +++ b/content/browser/loader/resource_scheduler.h
@@ -14,6 +14,7 @@ #include <vector> #include "base/compiler_specific.h" +#include "base/feature_list.h" #include "base/macros.h" #include "base/sequence_checker.h" #include "content/common/content_export.h" @@ -132,6 +133,7 @@ } private: + class Client; class RequestQueue; class ScheduledResourceRequest; struct RequestPriorityParams; @@ -139,7 +141,28 @@ bool operator()(const ScheduledResourceRequest* a, const ScheduledResourceRequest* b) const; }; - class Client; + + // Experiment parameters and helper functions for the throttling of delayable + // requests in the presence of non-delayable requests in-flight. + class NonDelayableThrottlesDelayableExperiment { + public: + NonDelayableThrottlesDelayableExperiment(); + + // This method computes the correct weight for the non-delayable requests + // based on the current effective connection type. If it is out of bounds, + // it returns 0, effectively disabling the experiment. + double GetCurrentNonDelayableWeight( + const net::NetworkQualityEstimator* network_quality_estimator) const; + + private: + // The maximum effective connection type for which the experiment should be + // enabled. + const net::EffectiveConnectionType max_effective_connection_type_; + + // The weight of a non-delayable request when counting the effective number + // of non-delayable requests in-flight. + const double non_delayable_weight_; + }; // Experiment parameters and helper functions for varying the maximum number // of delayable requests in-flight based on the observed bandwidth delay @@ -219,6 +242,11 @@ const MaxDelayableRequestsNetworkOverrideExperiment max_delayable_requests_network_override_experiment_; + // Parameters for the throttling of non-delayable requests in the + // presence of delayable requests. + const NonDelayableThrottlesDelayableExperiment + non_delayable_throttles_delayable_experiment_; + SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(ResourceScheduler);
diff --git a/content/browser/loader/resource_scheduler_unittest.cc b/content/browser/loader/resource_scheduler_unittest.cc index e6035de..28d9db3 100644 --- a/content/browser/loader/resource_scheduler_unittest.cc +++ b/content/browser/loader/resource_scheduler_unittest.cc
@@ -261,21 +261,13 @@ mock_timer_->Fire(); } - void InitializeMaxDelayableRequestsExperiment( - base::test::ScopedFeatureList* scoped_feature_list, - bool enabled) { + void InitializeExperiment(base::test::ScopedFeatureList* scoped_feature_list, + bool enabled, + const char* experiment_name, + const std::map<std::string, std::string>& params) { base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting(); const char kTrialName[] = "TrialName"; const char kGroupName[] = "GroupName"; - const char kMaxDelayableRequestsNetworkOverride[] = - "MaxDelayableRequestsNetworkOverride"; - - std::map<std::string, std::string> params; - params["MaxEffectiveConnectionType"] = "2G"; - params["MaxBDPKbits1"] = "130"; - params["MaxDelayableRequests1"] = "2"; - params["MaxBDPKbits2"] = "160"; - params["MaxDelayableRequests2"] = "4"; ASSERT_TRUE( base::AssociateFieldTrialParams(kTrialName, kGroupName, params)); @@ -286,7 +278,7 @@ std::unique_ptr<base::FeatureList> feature_list( base::MakeUnique<base::FeatureList>()); feature_list->RegisterFieldTrialOverride( - kMaxDelayableRequestsNetworkOverride, + experiment_name, enabled ? base::FeatureList::OVERRIDE_ENABLE_FEATURE : base::FeatureList::OVERRIDE_DISABLE_FEATURE, field_trial); @@ -365,6 +357,30 @@ } } + void InitializeMaxDelayableRequestsExperiment( + base::test::ScopedFeatureList* scoped_feature_list, + bool enabled) { + std::map<std::string, std::string> params; + params["MaxEffectiveConnectionType"] = "2G"; + params["MaxBDPKbits1"] = "130"; + params["MaxDelayableRequests1"] = "2"; + params["MaxBDPKbits2"] = "160"; + params["MaxDelayableRequests2"] = "4"; + InitializeExperiment(scoped_feature_list, enabled, + "MaxDelayableRequestsNetworkOverride", params); + } + + void InitializeNonDelayableThrottlesDelayableExperiment( + base::test::ScopedFeatureList* scoped_feature_list, + bool enabled, + double non_delayable_weight) { + std::map<std::string, std::string> params; + params["MaxEffectiveConnectionType"] = "2G"; + params["NonDelayableWeight"] = base::DoubleToString(non_delayable_weight); + InitializeExperiment(scoped_feature_list, enabled, + "NonDelayableThrottlesDelayable", params); + } + void ReadConfigTestHelper(size_t num_bdp_ranges, const std::string& max_ect_string) { base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting(); @@ -408,6 +424,79 @@ } } + void NonDelayableThrottlesDelayableConfigTestHelper(bool experiment_status) { + base::test::ScopedFeatureList scoped_feature_list; + const double kNonDelayableWeight = 2.0; + // Should be in sync with .cc. + const int kDefaultMaxNumDelayableRequestsPerClient = 10; + // Initialize the experiment with |kNonDelayableWeight| as the weight of + // non-delayable requests. + InitializeNonDelayableThrottlesDelayableExperiment( + &scoped_feature_list, experiment_status, kNonDelayableWeight); + // Experiment will only run when the effective connection type is slower + // than 2G. + network_quality_estimator_.set_effective_connection_type( + net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G); + + InitializeScheduler(); + // Limit will only trigger after the page has a body. + scheduler()->OnWillInsertBody(kChildId, kRouteId); + // Insert one non-delayable request, which should cause the limit for the + // number of delayable requests to go down by |kNonDelayableWeight|. + std::unique_ptr<TestRequest> medium( + NewRequest("http://host/medium", net::MEDIUM)); + ASSERT_TRUE(medium->started()); + // Start |kDefaultMaxNumDelayableRequestsPerClient| - 1 * + // |kNonDelayableWeight| delayable requests. + std::vector<std::unique_ptr<TestRequest>> delayable_requests; + for (int i = 0; + i < kDefaultMaxNumDelayableRequestsPerClient - kNonDelayableWeight; + ++i) { + delayable_requests.push_back(NewRequest( + base::StringPrintf("http://host%d/low", i).c_str(), net::LOWEST)); + EXPECT_TRUE(delayable_requests.back()->started()); + } + // A new non-delayable request should not start if the experiment is enabled + // because the weighted sum of the non-delayable request and the delayable + // requests in-flight is already |kDefaultMaxNumDelayableRequestsPerClient|. + std::unique_ptr<TestRequest> last_low( + NewRequest("http://lasthost/low", net::LOWEST)); + EXPECT_EQ(experiment_status, !last_low->started()); + } + + void NonDelayableThrottlesDelayableVaryWeightHelper( + double non_delayable_weight) { + base::test::ScopedFeatureList scoped_feature_list; + // Should be in sync with .cc. + const int kDefaultMaxNumDelayableRequestsPerClient = 10; + // Initialize the experiment. + InitializeNonDelayableThrottlesDelayableExperiment( + &scoped_feature_list, true, non_delayable_weight); + network_quality_estimator_.set_effective_connection_type( + net::EFFECTIVE_CONNECTION_TYPE_2G); + + InitializeScheduler(); + // Limit will only trigger after the page has a body. + scheduler()->OnWillInsertBody(kChildId, kRouteId); + // Start one non-delayable request. + std::unique_ptr<TestRequest> non_delayable_request( + NewRequest("http://host/medium", net::MEDIUM)); + // Start |kDefaultMaxNumDelayableRequestsPerClient - 1 * + // |non_delayable_weight| delayable requests. They should all start. + std::vector<std::unique_ptr<TestRequest>> delayable_requests; + for (int i = 0; + i < kDefaultMaxNumDelayableRequestsPerClient - non_delayable_weight; + ++i) { + delayable_requests.push_back(NewRequest( + base::StringPrintf("http://host%d/low", i).c_str(), net::LOWEST)); + EXPECT_TRUE(delayable_requests.back()->started()); + } + // The next delayable request should not start. + std::unique_ptr<TestRequest> last_low( + NewRequest("http://lasthost/low", net::LOWEST)); + EXPECT_FALSE(last_low->started()); + } + ResourceScheduler* scheduler() { return scheduler_.get(); } @@ -1475,6 +1564,154 @@ ReadConfigTestHelper(3, "4G"); } +// Test that the delayable requests are limited in the presence of non-delayable +// requests when the experiment is enabled. +TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableEnabledTest) { + NonDelayableThrottlesDelayableConfigTestHelper(true); +} + +// Test that the default limit is used for delayable requests when the +// experiment is disabled, even if non-delayable requests are present. +TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableDisabledTest) { + NonDelayableThrottlesDelayableConfigTestHelper(false); +} + +// Test that the default limit is used for delayable requests when the +// experiment is enabled, but the current effective connection type is higher +// than the maximum effective connection type set in the experiment +// configuration. +TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableOutsideECT) { + base::test::ScopedFeatureList scoped_feature_list; + const double kNonDelayableWeight = 2.0; + const int kDefaultMaxNumDelayableRequestsPerClient = + 10; // Should be in sync with cc. + // Initialize the experiment with |kNonDelayableWeight| as the weight of + // non-delayable requests. + InitializeNonDelayableThrottlesDelayableExperiment(&scoped_feature_list, true, + kNonDelayableWeight); + // Experiment should not run when the effective connection type is faster + // than 2G. + network_quality_estimator_.set_effective_connection_type( + net::EFFECTIVE_CONNECTION_TYPE_3G); + // Limit will only trigger after the page has a body. + + InitializeScheduler(); + scheduler()->OnWillInsertBody(kChildId, kRouteId); + // Insert one non-delayable request. This should not affect the number of + // delayable requests started. + std::unique_ptr<TestRequest> medium( + NewRequest("http://host/medium", net::MEDIUM)); + ASSERT_TRUE(medium->started()); + // Start |kDefaultMaxNumDelayableRequestsPerClient| delayable requests and + // verify that they all started. + std::vector<std::unique_ptr<TestRequest>> delayable_requests; + for (int i = 0; i < kDefaultMaxNumDelayableRequestsPerClient; ++i) { + delayable_requests.push_back(NewRequest( + base::StringPrintf("http://host%d/low", i).c_str(), net::LOWEST)); + EXPECT_TRUE(delayable_requests.back()->started()); + } +} + +// Test that delayable requests are throttled by the right amount as the number +// of non-delayable requests in-flight change. +TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableVaryNonDelayable) { + base::test::ScopedFeatureList scoped_feature_list; + const double kNonDelayableWeight = 2.0; + const int kDefaultMaxNumDelayableRequestsPerClient = + 10; // Should be in sync with cc. + // Initialize the experiment with |kNonDelayableWeight| as the weight of + // non-delayable requests. + InitializeNonDelayableThrottlesDelayableExperiment(&scoped_feature_list, true, + kNonDelayableWeight); + network_quality_estimator_.set_effective_connection_type( + net::EFFECTIVE_CONNECTION_TYPE_2G); + + InitializeScheduler(); + // Limit will only trigger after the page has a body. + scheduler()->OnWillInsertBody(kChildId, kRouteId); + for (int num_non_delayable = 0; num_non_delayable < 10; ++num_non_delayable) { + base::RunLoop().RunUntilIdle(); + // Start the non-delayable requests. + std::vector<std::unique_ptr<TestRequest>> non_delayable_requests; + for (int i = 0; i < num_non_delayable; ++i) { + non_delayable_requests.push_back(NewRequest( + base::StringPrintf("http://host%d/medium", i).c_str(), net::MEDIUM)); + ASSERT_TRUE(non_delayable_requests.back()->started()); + } + // Start |kDefaultMaxNumDelayableRequestsPerClient| - |num_non_delayable| * + // |kNonDelayableWeight| delayable requests. They should all start. + std::vector<std::unique_ptr<TestRequest>> delayable_requests; + for (int i = 0; i < kDefaultMaxNumDelayableRequestsPerClient - + num_non_delayable * kNonDelayableWeight; + ++i) { + delayable_requests.push_back(NewRequest( + base::StringPrintf("http://host%d/low", i).c_str(), net::LOWEST)); + EXPECT_TRUE(delayable_requests.back()->started()); + } + // The next delayable request should not start. + std::unique_ptr<TestRequest> last_low( + NewRequest("http://lasthost/low", net::LOWEST)); + EXPECT_FALSE(last_low->started()); + } +} + +// Test that the default limit is used for delayable requests in the presence of +// non-delayable requests when the non-delayable request weight is zero. +TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableWeight0) { + NonDelayableThrottlesDelayableVaryWeightHelper(0.0); +} + +// Test that each non-delayable request in-flight results in the reduction of +// one in the limit of delayable requests in-flight when the non-delayable +// request weight is 1. +TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableWeight1) { + NonDelayableThrottlesDelayableVaryWeightHelper(1.0); +} + +// Test that each non-delayable request in-flight results in the reduction of +// three in the limit of delayable requests in-flight when the non-delayable +// request weight is 3. +TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableWeight3) { + NonDelayableThrottlesDelayableVaryWeightHelper(3.0); +} + +// Test that UMA counts are recorded for the number of delayable requests +// in-flight when a non-delayable request starts. +TEST_F(ResourceSchedulerTest, NumDelayableAtStartOfNonDelayableUMA) { + std::unique_ptr<base::HistogramTester> histogram_tester( + new base::HistogramTester); + scheduler()->OnWillInsertBody(kChildId, kRouteId); + // Check that 0 is recorded when a non-delayable request starts and there are + // no delayable requests in-flight. + std::unique_ptr<TestRequest> high( + NewRequest("http://host/high", net::HIGHEST)); + EXPECT_TRUE(high->started()); + histogram_tester->ExpectUniqueSample( + "ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable", 0, + 1); + histogram_tester.reset(new base::HistogramTester); + // Check that nothing is recorded when delayable request is started in the + // presence of a non-delayable request. + std::unique_ptr<TestRequest> low1( + NewRequest("http://host/low1", net::LOWEST)); + EXPECT_TRUE(low1->started()); + histogram_tester->ExpectTotalCount( + "ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable", 0); + // Check that nothing is recorded when a delayable request is started in the + // presence of another delayable request. + std::unique_ptr<TestRequest> low2( + NewRequest("http://host/low2", net::LOWEST)); + histogram_tester->ExpectTotalCount( + "ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable", 0); + // Check that UMA is recorded when a non-delayable startes in the presence of + // delayable requests and that the correct value is recorded. + std::unique_ptr<TestRequest> high2( + NewRequest("http://host/high2", net::HIGHEST)); + histogram_tester->ExpectUniqueSample( + "ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable", 2, + 1); +} + } // unnamed namespace } // namespace content
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender.cc b/content/browser/service_worker/service_worker_installed_scripts_sender.cc index 643d820..bf4cbfed 100644 --- a/content/browser/service_worker/service_worker_installed_scripts_sender.cc +++ b/content/browser/service_worker/service_worker_installed_scripts_sender.cc
@@ -24,7 +24,7 @@ MetaDataSender(scoped_refptr<net::IOBufferWithSize> meta_data, mojo::ScopedDataPipeProducerHandle handle) : meta_data_(std::move(meta_data)), - remaining_bytes_(meta_data_->size()), + bytes_sent_(0), handle_(std::move(handle)), watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC), weak_factory_(this) {} @@ -36,10 +36,11 @@ base::Bind(&MetaDataSender::OnWritable, weak_factory_.GetWeakPtr())); } - void OnWritable(MojoResult result) { - DCHECK_EQ(MOJO_RESULT_OK, result); - uint32_t size = remaining_bytes_; - MojoResult rv = handle_->WriteData(meta_data_->data(), &size, + void OnWritable(MojoResult) { + // It isn't necessary to handle MojoResult here since WriteDataRaw() + // returns an equivalent error. + uint32_t size = meta_data_->size() - bytes_sent_; + MojoResult rv = handle_->WriteData(meta_data_->data() + bytes_sent_, &size, MOJO_WRITE_DATA_FLAG_NONE); switch (rv) { case MOJO_RESULT_INVALID_ARGUMENT: @@ -52,9 +53,15 @@ return; case MOJO_RESULT_SHOULD_WAIT: return; + case MOJO_RESULT_OK: + break; + default: + // mojo::WriteDataRaw() should not return any other values. + OnCompleted(Status::kFailed); + return; } - remaining_bytes_ -= size; - if (remaining_bytes_ == 0) + bytes_sent_ += size; + if (meta_data_->size() == bytes_sent_) OnCompleted(Status::kSuccess); } @@ -68,7 +75,7 @@ base::OnceCallback<void(Status)> callback_; scoped_refptr<net::IOBufferWithSize> meta_data_; - size_t remaining_bytes_; + int64_t bytes_sent_; mojo::ScopedDataPipeProducerHandle handle_; mojo::SimpleWatcher watcher_; @@ -102,15 +109,18 @@ DCHECK(http_info); DCHECK_GT(result, 0); if (!http_info->http_info) { - CompleteSendIfNeeded(Status::kNoHttpInfoError); + CompleteSendIfNeeded(FinishedReason::kNoHttpInfoError); return; } mojo::ScopedDataPipeConsumerHandle meta_data_consumer; mojo::ScopedDataPipeConsumerHandle body_consumer; + DCHECK_GE(http_info->response_data_size, 0); + uint64_t body_size = http_info->response_data_size; + uint64_t meta_data_size = 0; if (mojo::CreateDataPipe(nullptr, &body_handle_, &body_consumer) != MOJO_RESULT_OK) { - CompleteSendIfNeeded(Status::kCreateDataPipeError); + CompleteSendIfNeeded(FinishedReason::kCreateDataPipeError); return; } // Start sending meta data (V8 code cache data). @@ -118,13 +128,15 @@ mojo::ScopedDataPipeProducerHandle meta_data_producer; if (mojo::CreateDataPipe(nullptr, &meta_data_producer, &meta_data_consumer) != MOJO_RESULT_OK) { - CompleteSendIfNeeded(Status::kCreateDataPipeError); + CompleteSendIfNeeded(FinishedReason::kCreateDataPipeError); return; } meta_data_sender_ = base::MakeUnique<MetaDataSender>( http_info->http_info->metadata, std::move(meta_data_producer)); meta_data_sender_->Start( base::BindOnce(&Sender::OnMetaDataSent, AsWeakPtr())); + DCHECK_GE(http_info->http_info->metadata->size(), 0); + meta_data_size = http_info->http_info->metadata->size(); } // Start sending body. @@ -153,14 +165,15 @@ } } - owner_->SendScriptInfoToRenderer(charset, std::move(header_strings), - std::move(meta_data_consumer), - std::move(body_consumer)); + owner_->SendScriptInfoToRenderer( + charset, std::move(header_strings), std::move(body_consumer), body_size, + std::move(meta_data_consumer), meta_data_size); owner_->OnHttpInfoRead(http_info); } - void OnWritableBody(MojoResult result) { - DCHECK_EQ(MOJO_RESULT_OK, result); + void OnWritableBody(MojoResult) { + // It isn't necessary to handle MojoResult here since BeginWrite() returns + // an equivalent error. DCHECK(!pending_write_); uint32_t num_bytes = 0; MojoResult rv = NetToMojoPendingBuffer::BeginWrite( @@ -171,7 +184,7 @@ NOTREACHED(); return; case MOJO_RESULT_FAILED_PRECONDITION: - CompleteSendIfNeeded(Status::kConnectionError); + CompleteSendIfNeeded(FinishedReason::kConnectionError); return; case MOJO_RESULT_SHOULD_WAIT: watcher_.ArmOrNotify(); @@ -188,7 +201,9 @@ void OnResponseDataRead(int read_bytes) { if (read_bytes < 0) { - CompleteSendIfNeeded(Status::kResponseReaderError); + watcher_.Cancel(); + body_handle_.reset(); + CompleteSendIfNeeded(FinishedReason::kResponseReaderError); return; } body_handle_ = pending_write_->Complete(read_bytes); @@ -198,7 +213,7 @@ // All data has been read. watcher_.Cancel(); body_handle_.reset(); - CompleteSendIfNeeded(Status::kSuccess); + CompleteSendIfNeeded(FinishedReason::kSuccess); return; } watcher_.ArmOrNotify(); @@ -209,19 +224,19 @@ if (status != MetaDataSender::Status::kSuccess) { watcher_.Cancel(); body_handle_.reset(); - CompleteSendIfNeeded(Status::kMetaDataSenderError); + CompleteSendIfNeeded(FinishedReason::kMetaDataSenderError); return; } - CompleteSendIfNeeded(Status::kSuccess); + CompleteSendIfNeeded(FinishedReason::kSuccess); } // CompleteSendIfNeeded notifies the end of data transfer to |owner_|, and // |this| will be removed by |owner_| as a result. Errors are notified // immediately, but when the transfer has been succeeded, it's notified when // sending both of body and meta data is finished. - void CompleteSendIfNeeded(Status status) { - if (status != Status::kSuccess) { + void CompleteSendIfNeeded(FinishedReason status) { + if (status != FinishedReason::kSuccess) { owner_->OnAbortSendingScript(status); return; } @@ -256,6 +271,7 @@ main_script_url_(main_script_url), main_script_id_(kInvalidServiceWorkerResourceId), state_(State::kNotStarted), + finished_reason_(FinishedReason::kNotFinished), context_(std::move(context)) {} ServiceWorkerInstalledScriptsSender::~ServiceWorkerInstalledScriptsSender() {} @@ -284,6 +300,10 @@ return info; } +bool ServiceWorkerInstalledScriptsSender::IsFinished() const { + return state_ == State::kFinished; +} + void ServiceWorkerInstalledScriptsSender::Start() { DCHECK_EQ(State::kNotStarted, state_); // Return if no script has been installed. @@ -313,19 +333,24 @@ void ServiceWorkerInstalledScriptsSender::SendScriptInfoToRenderer( std::string encoding, std::unordered_map<std::string, std::string> headers, + mojo::ScopedDataPipeConsumerHandle body_handle, + uint64_t body_size, mojo::ScopedDataPipeConsumerHandle meta_data_handle, - mojo::ScopedDataPipeConsumerHandle body_handle) { + uint64_t meta_data_size) { DCHECK(running_sender_); DCHECK(state_ == State::kSendingMainScript || state_ == State::kSendingImportedScript); - TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("ServiceWorker", - "SendScriptInfoToRenderer", this); + TRACE_EVENT_NESTABLE_ASYNC_INSTANT2( + "ServiceWorker", "SendScriptInfoToRenderer", this, "body_size", body_size, + "meta_data_size", meta_data_size); auto script_info = mojom::ServiceWorkerScriptInfo::New(); script_info->script_url = CurrentSendingURL(); script_info->headers = std::move(headers); script_info->encoding = std::move(encoding); script_info->body = std::move(body_handle); + script_info->body_size = body_size; script_info->meta_data = std::move(meta_data_handle); + script_info->meta_data_size = meta_data_size; manager_->TransferInstalledScript(std::move(script_info)); } @@ -355,7 +380,9 @@ // All scripts have been sent to the renderer. // ServiceWorkerInstalledScriptsSender's work is done now. DCHECK_EQ(State::kSendingImportedScript, state_); + DCHECK(!IsFinished()); state_ = State::kFinished; + finished_reason_ = FinishedReason::kSuccess; TRACE_EVENT_NESTABLE_ASYNC_END0( "ServiceWorker", "ServiceWorkerInstalledScriptsSender", this); return; @@ -364,14 +391,23 @@ StartSendingScript(imported_script_iter_->first); } -void ServiceWorkerInstalledScriptsSender::OnAbortSendingScript(Status status) { +void ServiceWorkerInstalledScriptsSender::OnAbortSendingScript( + FinishedReason status) { DCHECK(running_sender_); DCHECK(state_ == State::kSendingMainScript || state_ == State::kSendingImportedScript); - DCHECK_NE(Status::kSuccess, status); - // TODO(shimazu): Report the error to ServiceWorkerVersion and record its - // metrics. - NOTIMPLEMENTED(); + DCHECK_NE(FinishedReason::kSuccess, status); + DCHECK(!IsFinished()); + TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", + "ServiceWorkerInstalledScriptsSender", this, + "FinishedReason", static_cast<int>(status)); + state_ = State::kFinished; + finished_reason_ = status; + + // Notify the renderer that the error occurred by resetting the Mojo + // pipe. This triggers failure of script loading on the renderer, and if it's + // the main script, it ends up with worker shutdown. + manager_.reset(); } const GURL& ServiceWorkerInstalledScriptsSender::CurrentSendingURL() {
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender.h b/content/browser/service_worker/service_worker_installed_scripts_sender.h index c6191bb..45e47ee 100644 --- a/content/browser/service_worker/service_worker_installed_scripts_sender.h +++ b/content/browser/service_worker/service_worker_installed_scripts_sender.h
@@ -19,6 +19,19 @@ // created for worker startup and lives as long as the worker is running. class CONTENT_EXPORT ServiceWorkerInstalledScriptsSender { public: + // Do not change the order. This is used for UMA. + enum class FinishedReason { + kNotFinished = 0, + kSuccess = 1, + kNoHttpInfoError = 2, + kCreateDataPipeError = 3, + kConnectionError = 4, + kResponseReaderError = 5, + kMetaDataSenderError = 6, + // Add a new type here, then update kMaxValue and enums.xml. + kMaxValue = kMetaDataSenderError, + }; + ServiceWorkerInstalledScriptsSender( ServiceWorkerVersion* owner, const GURL& main_script_url, @@ -33,18 +46,12 @@ // Starts sending installed scripts to the worker. void Start(); + bool IsFinished() const; + FinishedReason finished_reason() const { return finished_reason_; } + private: class Sender; - enum class Status { - kSuccess, - kNoHttpInfoError, - kCreateDataPipeError, - kConnectionError, - kResponseReaderError, - kMetaDataSenderError, - }; - enum class State { kNotStarted, kSendingMainScript, @@ -58,11 +65,13 @@ void SendScriptInfoToRenderer( std::string encoding, std::unordered_map<std::string, std::string> headers, + mojo::ScopedDataPipeConsumerHandle body_handle, + uint64_t body_size, mojo::ScopedDataPipeConsumerHandle meta_data_handle, - mojo::ScopedDataPipeConsumerHandle body_handle); + uint64_t meta_data_size); void OnHttpInfoRead(scoped_refptr<HttpResponseInfoIOBuffer> http_info); void OnFinishSendingScript(); - void OnAbortSendingScript(Status status); + void OnAbortSendingScript(FinishedReason status); const GURL& CurrentSendingURL(); @@ -73,6 +82,7 @@ mojom::ServiceWorkerInstalledScriptsManagerPtr manager_; std::unique_ptr<Sender> running_sender_; State state_; + FinishedReason finished_reason_; std::map<int64_t /* resource_id */, GURL> imported_scripts_; std::map<int64_t /* resource_id */, GURL>::iterator imported_script_iter_; base::WeakPtr<ServiceWorkerContextCore> context_;
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc b/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc index 8c374f5..01712571 100644 --- a/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc +++ b/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
@@ -154,11 +154,16 @@ } EXPECT_EQ(0u, script_info->headers.size()); EXPECT_TRUE(script_info->body.is_valid()); - EXPECT_TRUE(script_info->meta_data.is_valid()); std::string body = ReadDataPipe(std::move(script_info->body)); EXPECT_EQ(body_, body); - std::string meta_data = ReadDataPipe(std::move(script_info->meta_data)); - EXPECT_EQ(meta_data_, meta_data); + if (meta_data_.size() == 0) { + EXPECT_FALSE(script_info->meta_data.is_valid()); + EXPECT_EQ(0u, script_info->meta_data_size); + } else { + EXPECT_TRUE(script_info->meta_data.is_valid()); + std::string meta_data = ReadDataPipe(std::move(script_info->meta_data)); + EXPECT_EQ(meta_data_, meta_data); + } } const GURL& script_url() const { return script_url_; } @@ -254,18 +259,25 @@ scoped_refptr<ServiceWorkerVersion> version_; }; +using SenderFinishedReason = + ServiceWorkerInstalledScriptsSender::FinishedReason; + TEST_F(ServiceWorkerInstalledScriptsSenderTest, SendScripts) { const GURL kMainScriptURL = version()->script_url(); + std::string long_body = "I'm the script body!"; + std::string long_meta_data = "I'm the meta data!"; + long_body.resize(1E6, '!'); + long_meta_data.resize(1E6, '!'); std::map<GURL, ExpectedScriptInfo> kExpectedScriptInfoMap = { {kMainScriptURL, {1, kMainScriptURL, - {{"Content-Length", "19"}, + {{"Content-Length", "1000000"}, {"Content-Type", "text/javascript; charset=utf-8"}, {"TestHeader", "BlahBlah"}}, "utf-8", - "I'm the script body!", - "I'm the meta data!"}}, + std::move(long_body), + std::move(long_meta_data)}}, {GURL("https://example.com/imported1"), {2, GURL("https://example.com/imported1"), @@ -278,12 +290,12 @@ {GURL("https://example.com/imported2"), {3, GURL("https://example.com/imported2"), - {{"Content-Length", "22"}, + {{"Content-Length", "0"}, {"Content-Type", "text/javascript; charset=shift_jis"}, {"TestHeader", "BlahBlah"}}, "shift_jis", - "I'm imported script 2!", - "I'm the meta data for imported script 2!"}}, + "", + ""}}, }; { @@ -323,6 +335,130 @@ info.CheckIfIdentical(script_info); kExpectedScriptInfoMap.erase(script_info->script_url); } + + EXPECT_TRUE(sender->IsFinished()); + EXPECT_EQ(SenderFinishedReason::kSuccess, sender->finished_reason()); +} + +TEST_F(ServiceWorkerInstalledScriptsSenderTest, FailedToSendBody) { + const GURL kMainScriptURL = version()->script_url(); + std::string long_body = "I'm the body"; + long_body.resize(1E6, '!'); + std::map<GURL, ExpectedScriptInfo> kExpectedScriptInfoMap = { + {kMainScriptURL, + {1, + kMainScriptURL, + {{"Content-Length", "1000000"}, + {"Content-Type", "text/javascript; charset=utf-8"}, + {"TestHeader", "BlahBlah"}}, + "utf-8", + std::move(long_body), + "I'm the meta data!"}}, + }; + + { + std::vector<ServiceWorkerDatabase::ResourceRecord> records; + for (const auto& info : kExpectedScriptInfoMap) + records.push_back(info.second.WriteToDiskCache(context()->storage())); + version()->script_cache_map()->SetResources(records); + } + + auto sender = base::MakeUnique<ServiceWorkerInstalledScriptsSender>( + version(), kMainScriptURL, context()->AsWeakPtr()); + + std::unique_ptr<MockServiceWorkerInstalledScriptsManager> renderer_manager; + { + mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info = + sender->CreateInfoAndBind(); + ASSERT_TRUE(scripts_info); + ASSERT_EQ(kExpectedScriptInfoMap.size(), + scripts_info->installed_urls.size()); + for (const auto& url : scripts_info->installed_urls) + EXPECT_TRUE(base::ContainsKey(kExpectedScriptInfoMap, url)); + EXPECT_TRUE(scripts_info->manager_request.is_pending()); + renderer_manager = + base::MakeUnique<MockServiceWorkerInstalledScriptsManager>( + std::move(scripts_info->installed_urls), + std::move(scripts_info->manager_request)); + } + ASSERT_TRUE(renderer_manager); + + sender->Start(); + + { + // Reset a data pipe during sending the body. + auto script_info = renderer_manager->WaitUntilTransferInstalledScript(); + EXPECT_TRUE( + base::ContainsKey(kExpectedScriptInfoMap, script_info->script_url)); + script_info->body.reset(); + kExpectedScriptInfoMap.erase(script_info->script_url); + // Wait until the error is triggered on the sender side. + base::RunLoop().RunUntilIdle(); + } + + EXPECT_TRUE(sender->IsFinished()); + EXPECT_EQ(SenderFinishedReason::kConnectionError, sender->finished_reason()); +} + +TEST_F(ServiceWorkerInstalledScriptsSenderTest, FailedToSendMetaData) { + const GURL kMainScriptURL = version()->script_url(); + std::string long_meta_data = "I'm the meta data!"; + long_meta_data.resize(1E6, '!'); + std::map<GURL, ExpectedScriptInfo> kExpectedScriptInfoMap = { + {kMainScriptURL, + {1, + kMainScriptURL, + {{"Content-Length", "0"}, + {"Content-Type", "text/javascript; charset=utf-8"}, + {"TestHeader", "BlahBlah"}}, + "utf-8", + "", + std::move(long_meta_data)}}, + }; + + { + std::vector<ServiceWorkerDatabase::ResourceRecord> records; + for (const auto& info : kExpectedScriptInfoMap) + records.push_back(info.second.WriteToDiskCache(context()->storage())); + version()->script_cache_map()->SetResources(records); + } + + auto sender = base::MakeUnique<ServiceWorkerInstalledScriptsSender>( + version(), kMainScriptURL, context()->AsWeakPtr()); + + std::unique_ptr<MockServiceWorkerInstalledScriptsManager> renderer_manager; + { + mojom::ServiceWorkerInstalledScriptsInfoPtr scripts_info = + sender->CreateInfoAndBind(); + ASSERT_TRUE(scripts_info); + ASSERT_EQ(kExpectedScriptInfoMap.size(), + scripts_info->installed_urls.size()); + for (const auto& url : scripts_info->installed_urls) + EXPECT_TRUE(base::ContainsKey(kExpectedScriptInfoMap, url)); + EXPECT_TRUE(scripts_info->manager_request.is_pending()); + renderer_manager = + base::MakeUnique<MockServiceWorkerInstalledScriptsManager>( + std::move(scripts_info->installed_urls), + std::move(scripts_info->manager_request)); + } + ASSERT_TRUE(renderer_manager); + + sender->Start(); + + { + // Reset a data pipe during sending the meta data. + auto script_info = renderer_manager->WaitUntilTransferInstalledScript(); + EXPECT_TRUE( + base::ContainsKey(kExpectedScriptInfoMap, script_info->script_url)); + script_info->meta_data.reset(); + kExpectedScriptInfoMap.erase(script_info->script_url); + // Wait until the error is triggered on the sender side. + base::RunLoop().RunUntilIdle(); + } + + EXPECT_TRUE(sender->IsFinished()); + EXPECT_EQ(SenderFinishedReason::kMetaDataSenderError, + sender->finished_reason()); } } // namespace content
diff --git a/content/browser/service_worker/service_worker_metrics.cc b/content/browser/service_worker/service_worker_metrics.cc index 104962b..5efdbeb 100644 --- a/content/browser/service_worker/service_worker_metrics.cc +++ b/content/browser/service_worker/service_worker_metrics.cc
@@ -497,16 +497,21 @@ RecordHistogramEnum(std::string("ServiceWorker.StartWorker.StatusByPurpose") + EventTypeToSuffix(purpose), status, SERVICE_WORKER_ERROR_MAX_VALUE); - UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Purpose", - static_cast<int>(purpose), - static_cast<int>(EventType::NUM_TYPES)); + UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Purpose", purpose, + EventType::NUM_TYPES); if (status == SERVICE_WORKER_ERROR_TIMEOUT) { UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Timeout.StartPurpose", - static_cast<int>(purpose), - static_cast<int>(EventType::NUM_TYPES)); + purpose, EventType::NUM_TYPES); } } +void ServiceWorkerMetrics::RecordInstalledScriptsSenderStatus( + ServiceWorkerInstalledScriptsSender::FinishedReason reason) { + UMA_HISTOGRAM_ENUMERATION( + "ServiceWorker.StartWorker.InstalledScriptsSender.FinishedReason", reason, + ServiceWorkerInstalledScriptsSender::FinishedReason::kMaxValue); +} + void ServiceWorkerMetrics::RecordStartWorkerTime(base::TimeDelta time, bool is_installed, StartSituation start_situation,
diff --git a/content/browser/service_worker/service_worker_metrics.h b/content/browser/service_worker/service_worker_metrics.h index bb466d3..526390d 100644 --- a/content/browser/service_worker/service_worker_metrics.h +++ b/content/browser/service_worker/service_worker_metrics.h
@@ -13,6 +13,7 @@ #include "base/time/time.h" #include "content/browser/service_worker/service_worker_context_request_handler.h" #include "content/browser/service_worker/service_worker_database.h" +#include "content/browser/service_worker/service_worker_installed_scripts_sender.h" #include "content/common/service_worker/embedded_worker.mojom.h" #include "content/common/service_worker/service_worker_types.h" #include "content/public/browser/service_worker_context.h" @@ -270,6 +271,10 @@ EventType purpose, bool is_installed); + // Records the result of sending installed scripts to the renderer. + static void RecordInstalledScriptsSenderStatus( + ServiceWorkerInstalledScriptsSender::FinishedReason reason); + // Records the time taken to successfully start a worker. |is_installed| // indicates whether the version has been installed. static void RecordStartWorkerTime(base::TimeDelta time,
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 3f1df99..2287915 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -1713,6 +1713,10 @@ if (context_ && IsInstalled(prestart_status)) context_->UpdateVersionFailureCount(version_id_, status); + if (installed_scripts_sender_) { + ServiceWorkerMetrics::RecordInstalledScriptsSenderStatus( + installed_scripts_sender_->finished_reason()); + } ServiceWorkerMetrics::RecordStartWorkerStatus(status, purpose, IsInstalled(prestart_status));
diff --git a/content/browser/tracing/memory_tracing_browsertest.cc b/content/browser/tracing/memory_tracing_browsertest.cc index 3733caa..56e17ec9 100644 --- a/content/browser/tracing/memory_tracing_browsertest.cc +++ b/content/browser/tracing/memory_tracing_browsertest.cc
@@ -236,7 +236,8 @@ // dump requests are queued and carried out after it's finished. Also checks // that periodic dump requests fail in case there is already a request in the // queue with the same level of detail. -IN_PROC_BROWSER_TEST_F(SingleProcessMemoryTracingTest, QueuedDumps) { +// Flaky failures on all platforms. https://crbug.com/752613 +IN_PROC_BROWSER_TEST_F(SingleProcessMemoryTracingTest, DISABLED_QueuedDumps) { Navigate(shell()); EnableMemoryTracing();
diff --git a/content/common/sandbox_win.cc b/content/common/sandbox_win.cc index 4719a0e..4b81aca 100644 --- a/content/common/sandbox_win.cc +++ b/content/common/sandbox_win.cc
@@ -763,14 +763,12 @@ sandbox::MITIGATION_BOTTOM_UP_ASLR | sandbox::MITIGATION_DEP | sandbox::MITIGATION_DEP_NO_ATL_THUNK | + sandbox::MITIGATION_EXTENSION_POINT_DISABLE | sandbox::MITIGATION_SEHOP | sandbox::MITIGATION_NONSYSTEM_FONT_DISABLE | sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE | sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL; - if (base::FeatureList::IsEnabled(features::kWinSboxDisableExtensionPoints)) - mitigations |= sandbox::MITIGATION_EXTENSION_POINT_DISABLE; - sandbox::ResultCode result = sandbox::SBOX_ERROR_GENERIC; result = policy->SetProcessMitigations(mitigations); @@ -788,6 +786,8 @@ // Post-startup mitigations. mitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS | sandbox::MITIGATION_DLL_SEARCH_ORDER; + if (base::FeatureList::IsEnabled(features::kWinSboxForceMsSigned)) + mitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS; result = policy->SetDelayedProcessMitigations(mitigations); if (result != sandbox::SBOX_ALL_OK)
diff --git a/content/common/service_worker/service_worker_installed_scripts_manager.mojom b/content/common/service_worker/service_worker_installed_scripts_manager.mojom index fc8731c3..6179b27 100644 --- a/content/common/service_worker/service_worker_installed_scripts_manager.mojom +++ b/content/common/service_worker/service_worker_installed_scripts_manager.mojom
@@ -22,9 +22,11 @@ map<string, string> headers; // A handle for receiving the script body. handle<data_pipe_consumer> body; + uint64 body_size; // A handle for receiving the V8 code cached metadata. This is null when no // meta data is available. handle<data_pipe_consumer>? meta_data; + uint64 meta_data_size; }; // Renderer-side interface. The browser uses this interface to send
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 3d31816..f2b89f1 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -71,6 +71,12 @@ const base::Feature kCompositorTouchAction{"CompositorTouchAction", base::FEATURE_DISABLED_BY_DEFAULT}; +// Controls whether PreferCompositingToLCDText is forced off, even for +// screens with high resolution. +const base::Feature kDisablePreferCompositingToLCDTextOnLowEndAndroid{ + "DisablePreferCompositingToLCDTextOnLowEndAndroid", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Throttle tasks in Blink background timer queues based on CPU budgets // for the background tab. Bug: https://crbug.com/639852. const base::Feature kExpensiveBackgroundTimerThrottling{ @@ -250,6 +256,11 @@ const base::Feature kScrollAnchoring{"ScrollAnchoring", base::FEATURE_ENABLED_BY_DEFAULT}; +// Make sendBeacon throw for a Blob with a non simple type. +const base::Feature kSendBeaconThrowForBlobWithNonSimpleType{ + "SendBeaconThrowForBlobWithNonSimpleType", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Navigation preload feature of service workers. const base::Feature kServiceWorkerNavigationPreload{ "ServiceWorkerNavigationPreload", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -382,11 +393,6 @@ const base::Feature kWebVRExperimentalRendering{ "WebVRExperimentalRendering", base::FEATURE_DISABLED_BY_DEFAULT}; -// Make sendBeacon throw for a Blob with a non simple type. -const base::Feature kSendBeaconThrowForBlobWithNonSimpleType{ - "SendBeaconThrowForBlobWithNonSimpleType", - base::FEATURE_DISABLED_BY_DEFAULT}; - #if defined(OS_ANDROID) // Autofill Accessibility in Android. // crbug.com/627860 @@ -406,20 +412,19 @@ // Controls whether the WebNFC API is enabled: // https://w3c.github.io/web-nfc/ const base::Feature kWebNfc{"WebNFC", base::FEATURE_DISABLED_BY_DEFAULT}; -#endif - -// Controls whether PreferCompositingToLCDText is forced off, even for -// screens with high resolution. -const base::Feature kDisablePreferCompositingToLCDTextOnLowEndAndroid{ - "DisablePreferCompositingToLCDTextOnLowEndAndroid", - base::FEATURE_DISABLED_BY_DEFAULT}; +#endif // defined(OS_ANDROID) #if defined(OS_WIN) // Emergency "off switch" for new Windows sandbox security mitigation, // sandbox::MITIGATION_EXTENSION_POINT_DISABLE. const base::Feature kWinSboxDisableExtensionPoints{ "WinSboxDisableExtensionPoint", base::FEATURE_ENABLED_BY_DEFAULT}; -#endif + +// Emergency "off switch" for new Windows sandbox security mitigation, +// sandbox::MITIGATION_FORCE_MS_SIGNED_BINS. +const base::Feature kWinSboxForceMsSigned{"WinSboxForceMsSigned", + base::FEATURE_ENABLED_BY_DEFAULT}; +#endif // defined(OS_WIN) #if defined(OS_MACOSX) // Enables caching of media devices for the purpose of enumerating them.
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index d1519ca..56c58f9f 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -29,6 +29,8 @@ CONTENT_EXPORT extern const base::Feature kCompositeOpaqueFixedPosition; CONTENT_EXPORT extern const base::Feature kCompositeOpaqueScrollers; CONTENT_EXPORT extern const base::Feature kCompositorTouchAction; +CONTENT_EXPORT extern const base::Feature + kDisablePreferCompositingToLCDTextOnLowEndAndroid; CONTENT_EXPORT extern const base::Feature kExpensiveBackgroundTimerThrottling; CONTENT_EXPORT extern const base::Feature kFeaturePolicy; CONTENT_EXPORT extern const base::Feature kFetchKeepaliveTimeoutSetting; @@ -67,6 +69,8 @@ CONTENT_EXPORT extern const base::Feature kReportRendererPeakMemoryStats; CONTENT_EXPORT extern const base::Feature kResourceLoadScheduler; CONTENT_EXPORT extern const base::Feature kScrollAnchoring; +CONTENT_EXPORT +extern const base::Feature kSendBeaconThrowForBlobWithNonSimpleType; CONTENT_EXPORT extern const base::Feature kServiceWorkerNavigationPreload; CONTENT_EXPORT extern const base::Feature kServiceWorkerScriptStreaming; CONTENT_EXPORT extern const base::Feature kSharedArrayBuffer; @@ -93,8 +97,6 @@ CONTENT_EXPORT extern const base::Feature kWebRtcUseGpuMemoryBufferVideoFrames; CONTENT_EXPORT extern const base::Feature kWebUsb; CONTENT_EXPORT extern const base::Feature kWebVRExperimentalRendering; -CONTENT_EXPORT -extern const base::Feature kSendBeaconThrowForBlobWithNonSimpleType; #if defined(OS_ANDROID) CONTENT_EXPORT extern const base::Feature kAndroidAutofillAccessibility; @@ -104,11 +106,9 @@ CONTENT_EXPORT extern const base::Feature kWebNfc; #endif // defined(OS_ANDROID) -CONTENT_EXPORT extern const base::Feature - kDisablePreferCompositingToLCDTextOnLowEndAndroid; - #if defined(OS_WIN) CONTENT_EXPORT extern const base::Feature kWinSboxDisableExtensionPoints; +CONTENT_EXPORT extern const base::Feature kWinSboxForceMsSigned; #endif // defined(OS_WIN) #if defined(OS_MACOSX)
diff --git a/content/renderer/media/audio_renderer_sink_cache_unittest.cc b/content/renderer/media/audio_renderer_sink_cache_unittest.cc index 846b016..2d136a7 100644 --- a/content/renderer/media/audio_renderer_sink_cache_unittest.cc +++ b/content/renderer/media/audio_renderer_sink_cache_unittest.cc
@@ -11,6 +11,7 @@ #include "base/test/test_simple_task_runner.h" #include "base/test/test_timeouts.h" #include "base/threading/thread.h" +#include "build/build_config.h" #include "content/renderer/media/audio_renderer_sink_cache_impl.h" #include "media/audio/audio_device_description.h" #include "media/base/audio_parameters.h" @@ -303,7 +304,14 @@ // Check that a sink created on one thread in response to GetSinkInfo can be // used on another thread. -TEST_F(AudioRendererSinkCacheTest, MultithreadedAccess) { +// Flaky on Linux TSan Tests. https://crbug.com/753228 +#if defined(OS_LINUX) +#define MAYBE_MultithreadedAccess DISABLED_MultithreadedAccess +#else +#define MAYBE_MultithreadedAccess MultithreadedAccess +#endif + +TEST_F(AudioRendererSinkCacheTest, MAYBE_MultithreadedAccess) { EXPECT_EQ(0, sink_count()); base::Thread thread1("thread1");
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index e5b7da6..913f1a89 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -5246,8 +5246,10 @@ weak_factory_.GetWeakPtr()); // Chrome doesn't use interface versioning. - url_loader_factory_.Bind(mojom::URLLoaderFactoryPtrInfo( + mojom::URLLoaderFactoryPtr url_loader_factory; + url_loader_factory.Bind(mojom::URLLoaderFactoryPtrInfo( mojo::ScopedMessagePipeHandle(commit_data.url_loader_factory), 0u)); + url_loader_factory_ = std::move(url_loader_factory); // If the request was initiated in the context of a user gesture then make // sure that the navigation also executes in the context of a user gesture. @@ -6825,23 +6827,28 @@ UpdatePeakMemoryStats(); ChildThreadImpl* child_thread = ChildThreadImpl::current(); - if (base::FeatureList::IsEnabled(features::kNetworkService) && child_thread) { - // Use if per-frame or per-scheme URLLoaderFactory is given. - mojom::URLLoaderFactory* factory = url_loader_factory_.get(); - - if (request.Url().ProtocolIs(url::kBlobScheme)) - factory = RenderThreadImpl::current()->GetBlobURLLoaderFactory(); - - if (factory) { - return base::MakeUnique<WebURLLoaderImpl>( - child_thread->resource_dispatcher(), task_runner, factory); - } - // Otherwise fallback to the platform one, which will use the default - // network service's URLLoaderFactory. + if (!child_thread) { + return RenderThreadImpl::current()->blink_platform_impl()->CreateURLLoader( + request, task_runner); } - return RenderThreadImpl::current()->blink_platform_impl()->CreateURLLoader( - request, task_runner); + mojom::URLLoaderFactory* factory = url_loader_factory_.get(); + if (base::FeatureList::IsEnabled(features::kNetworkService) && + request.Url().ProtocolIs(url::kBlobScheme)) { + factory = RenderThreadImpl::current()->GetBlobURLLoaderFactory(); + DCHECK(factory); + } + + if (!factory && !url_loader_factory_) { + url_loader_factory_ = RenderThreadImpl::current() + ->blink_platform_impl() + ->CreateURLLoaderFactory(); + factory = url_loader_factory_.get(); + DCHECK(factory); + } + + return base::MakeUnique<WebURLLoaderImpl>(child_thread->resource_dispatcher(), + task_runner, factory); } void RenderFrameImpl::DraggableRegionsChanged() {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 88ca1d1..1f9d303 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -34,6 +34,7 @@ #include "content/common/frame.mojom.h" #include "content/common/frame_message_enums.h" #include "content/common/host_zoom.mojom.h" +#include "content/common/possibly_associated_interface_ptr.h" #include "content/common/renderer.mojom.h" #include "content/common/unique_name_helper.h" #include "content/common/widget.mojom.h" @@ -1476,7 +1477,7 @@ mojo::BindingSet<service_manager::mojom::InterfaceProvider> interface_provider_bindings_; - mojom::URLLoaderFactoryPtr url_loader_factory_; + PossiblyAssociatedInterfacePtr<mojom::URLLoaderFactory> url_loader_factory_; // AndroidOverlay routing token from the browser, if we have one yet. base::Optional<base::UnguessableToken> overlay_routing_token_;
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 5469dc00..f94605a 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -316,26 +316,8 @@ base::SingleThreadTaskRunner* task_runner) { ChildThreadImpl* child_thread = ChildThreadImpl::current(); - if (!url_loader_factory_ && child_thread) { - if (base::FeatureList::IsEnabled(features::kNetworkService)) { - mojom::URLLoaderFactoryPtr factory_ptr; - connector_->BindInterface(mojom::kBrowserServiceName, &factory_ptr); - url_loader_factory_ = std::move(factory_ptr); - } else { - mojom::URLLoaderFactoryAssociatedPtr factory_ptr; - child_thread->channel()->GetRemoteAssociatedInterface(&factory_ptr); - url_loader_factory_ = std::move(factory_ptr); - } - - // Attach the CORS-enabled URLLoader if we use the default (non-custom) - // network URLLoader. - if (base::FeatureList::IsEnabled(features::kOutOfBlinkCORS)) { - mojom::URLLoaderFactoryPtr factory_ptr; - CORSURLLoaderFactory::CreateAndBind(std::move(url_loader_factory_), - mojo::MakeRequest(&factory_ptr)); - url_loader_factory_ = std::move(factory_ptr); - } - } + if (!url_loader_factory_ && child_thread) + url_loader_factory_ = CreateURLLoaderFactory(); // There may be no child thread in RenderViewTests. These tests can still use // data URLs to bypass the ResourceDispatcher. @@ -344,6 +326,33 @@ url_loader_factory_.get()); } +PossiblyAssociatedInterfacePtr<mojom::URLLoaderFactory> +RendererBlinkPlatformImpl::CreateURLLoaderFactory() { + ChildThreadImpl* child_thread = ChildThreadImpl::current(); + DCHECK(child_thread); + PossiblyAssociatedInterfacePtr<mojom::URLLoaderFactory> url_loader_factory; + + if (base::FeatureList::IsEnabled(features::kNetworkService)) { + mojom::URLLoaderFactoryPtr factory_ptr; + connector_->BindInterface(mojom::kBrowserServiceName, &factory_ptr); + url_loader_factory = std::move(factory_ptr); + } else { + mojom::URLLoaderFactoryAssociatedPtr factory_ptr; + child_thread->channel()->GetRemoteAssociatedInterface(&factory_ptr); + url_loader_factory = std::move(factory_ptr); + } + + // Attach the CORS-enabled URLLoader if we use the default (non-custom) + // network URLLoader. + if (base::FeatureList::IsEnabled(features::kOutOfBlinkCORS)) { + mojom::URLLoaderFactoryPtr factory_ptr; + CORSURLLoaderFactory::CreateAndBind(std::move(url_loader_factory_), + mojo::MakeRequest(&factory_ptr)); + url_loader_factory = std::move(factory_ptr); + } + return url_loader_factory; +} + blink::WebThread* RendererBlinkPlatformImpl::CurrentThread() { if (main_thread_->IsCurrentThread()) return main_thread_.get();
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h index 0ca8faf4..300600e 100644 --- a/content/renderer/renderer_blink_platform_impl.h +++ b/content/renderer/renderer_blink_platform_impl.h
@@ -248,6 +248,9 @@ void RequestPurgeMemory() override; + PossiblyAssociatedInterfacePtr<mojom::URLLoaderFactory> + CreateURLLoaderFactory(); + private: bool CheckPreparsedJsCachingEnabled() const;
diff --git a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc index 7ae9fa57..223660b5 100644 --- a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc +++ b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc
@@ -22,9 +22,10 @@ public: using BytesChunk = blink::WebVector<char>; - explicit Receiver(mojo::ScopedDataPipeConsumerHandle handle) + Receiver(mojo::ScopedDataPipeConsumerHandle handle, uint64_t total_bytes) : handle_(std::move(handle)), - watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL) {} + watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL), + remaining_bytes_(total_bytes) {} void Start(base::OnceClosure callback) { if (!handle_.is_valid()) { @@ -33,12 +34,15 @@ } callback_ = std::move(callback); // base::Unretained is safe because |watcher_| is owned by |this|. - watcher_.Watch(handle_.get(), MOJO_HANDLE_SIGNAL_READABLE, + watcher_.Watch(handle_.get(), + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, base::Bind(&Receiver::OnReadable, base::Unretained(this))); watcher_.ArmOrNotify(); } - void OnReadable(MojoResult /* unused */) { + void OnReadable(MojoResult) { + // It isn't necessary to handle MojoResult here since BeginReadDataRaw() + // returns an equivalent error. const void* buffer = nullptr; uint32_t bytes_read = 0; MojoResult rv = @@ -50,16 +54,19 @@ return; case MOJO_RESULT_FAILED_PRECONDITION: // Closed by peer. - watcher_.Cancel(); - handle_.reset(); - DCHECK(callback_); - std::move(callback_).Run(); + OnCompleted(); return; case MOJO_RESULT_SHOULD_WAIT: watcher_.ArmOrNotify(); return; case MOJO_RESULT_OK: break; + default: + // mojo::BeginReadDataRaw() should not return any other values. + // Notify the error to the browser by resetting the handle even though + // it's in the middle of data transfer. + OnCompleted(); + return; } if (bytes_read > 0) @@ -67,10 +74,13 @@ rv = handle_->EndReadData(bytes_read); DCHECK_EQ(rv, MOJO_RESULT_OK); + CHECK_GE(remaining_bytes_, bytes_read); + remaining_bytes_ -= bytes_read; watcher_.ArmOrNotify(); } bool is_running() const { return handle_.is_valid(); } + bool has_received_all_data() const { return remaining_bytes_ == 0; } blink::WebVector<BytesChunk> TakeChunks() { DCHECK(!is_running()); @@ -78,6 +88,15 @@ } private: + void OnCompleted() { + handle_.reset(); + watcher_.Cancel(); + if (!has_received_all_data()) + chunks_.clear(); + DCHECK(callback_); + std::move(callback_).Run(); + } + base::OnceClosure callback_; mojo::ScopedDataPipeConsumerHandle handle_; mojo::SimpleWatcher watcher_; @@ -85,6 +104,7 @@ // std::vector is internally used because blink::WebVector is immutable and // cannot append data. std::vector<BytesChunk> chunks_; + uint64_t remaining_bytes_; }; // BundledReceivers is a helper class to wait for the end of reading body and @@ -92,9 +112,11 @@ class BundledReceivers { public: BundledReceivers(mojo::ScopedDataPipeConsumerHandle meta_data_handle, - mojo::ScopedDataPipeConsumerHandle body_handle) - : meta_data_(std::move(meta_data_handle)), - body_(std::move(body_handle)) {} + uint64_t meta_data_size, + mojo::ScopedDataPipeConsumerHandle body_handle, + uint64_t body_size) + : meta_data_(std::move(meta_data_handle), meta_data_size), + body_(std::move(body_handle), body_size) {} // Starts reading the pipes and invokes |callback| when both are finished. void Start(base::OnceClosure callback) { @@ -147,7 +169,8 @@ DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_); GURL script_url = script_info->script_url; auto receivers = base::MakeUnique<BundledReceivers>( - std::move(script_info->meta_data), std::move(script_info->body)); + std::move(script_info->meta_data), script_info->meta_data_size, + std::move(script_info->body), script_info->body_size); receivers->Start(base::BindOnce(&Internal::OnScriptReceived, weak_factory_.GetWeakPtr(), base::Passed(&script_info))); @@ -163,6 +186,16 @@ DCHECK(iter != running_receivers_.end()); std::unique_ptr<BundledReceivers> receivers = std::move(iter->second); DCHECK(receivers); + if (!receivers->body()->has_received_all_data() || + !receivers->meta_data()->has_received_all_data()) { + // TODO(shimazu): Add a RawScriptData with a failure flag to + // |script_container_| in order to distinguish failure of receiving the + // script from getting the script twice. + running_receivers_.erase(iter); + script_container_->OnAllDataAddedOnIOThread(); + return; + } + auto script_data = blink::WebServiceWorkerInstalledScriptsManager::RawScriptData::Create( blink::WebString::FromUTF8(script_info->encoding),
diff --git a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc index 783b67db0..41fa0677 100644 --- a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc +++ b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc
@@ -28,7 +28,8 @@ return scripts_info; } - const GURL& TransferInstalledScript() { + const GURL& TransferInstalledScript(int64_t body_size, + int64_t meta_data_size) { EXPECT_FALSE(body_handle_.is_valid()); EXPECT_FALSE(meta_data_handle_.is_valid()); auto script_info = mojom::ServiceWorkerScriptInfo::New(); @@ -38,6 +39,8 @@ mojo::CreateDataPipe(nullptr, &body_handle_, &script_info->body)); EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(nullptr, &meta_data_handle_, &script_info->meta_data)); + script_info->body_size = body_size; + script_info->meta_data_size = meta_data_size; manager_->TransferInstalledScript(std::move(script_info)); next_transfer_index_++; return transferring_url; @@ -55,13 +58,15 @@ void FinishTransferMetaData() { meta_data_handle_.reset(); } + void ResetManager() { manager_.reset(); } + const std::vector<GURL>& installed_urls() const { return installed_urls_; } private: void PushDataPipe(const std::string& data, const mojo::DataPipeProducerHandle& handle) { - ASSERT_TRUE(handle.is_valid()); // Send |data| with null terminator. + ASSERT_TRUE(handle.is_valid()); uint32_t written_bytes = data.size() + 1; MojoResult rv = handle.WriteData(data.c_str(), &written_bytes, MOJO_WRITE_DATA_FLAG_NONE); @@ -196,8 +201,10 @@ base::WaitableEvent* get_raw_script_data_waiter = GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data); - // Start transferring the script. - EXPECT_EQ(kScriptUrl, sender.TransferInstalledScript()); + // Start transferring the script. +1 for null terminator. + EXPECT_EQ(kScriptUrl, + sender.TransferInstalledScript(kExpectedBody.size() + 1, + kExpectedMetaData.size() + 1)); sender.PushBody(kExpectedBody); sender.PushMetaData(kExpectedMetaData); // GetRawScriptData should be blocked until body and meta data transfer are @@ -225,7 +232,130 @@ std::unique_ptr<RawScriptData> script_data; GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data)->Wait(); // This should not be blocked because the script has already been received. - // nullptr will be served after the data has already been taken. + // nullptr will be returned after the data has already been taken. + EXPECT_EQ(nullptr, script_data.get()); + } +} + +TEST_F(WebServiceWorkerInstalledScriptsManagerImplTest, + EarlyDisconnectionBody) { + const GURL kScriptUrl = GURL("https://example.com/installed1.js"); + const GURL kUnknownScriptUrl = GURL("https://example.com/not_installed.js"); + + BrowserSideSender sender({kScriptUrl}); + CreateInstalledScriptsManager(sender.CreateAndBind()); + + { + std::unique_ptr<RawScriptData> script_data; + const std::string kExpectedBody = "This is a script body."; + const std::string kExpectedMetaData = "This is a meta data."; + base::WaitableEvent* get_raw_script_data_waiter = + GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data); + + // Start transferring the script. + // Body is expected to be 100 bytes larger than kExpectedBody, but sender + // only sends kExpectedBody and a null byte (kExpectedBody.size() + 1 bytes + // in total). + EXPECT_EQ(kScriptUrl, + sender.TransferInstalledScript(kExpectedBody.size() + 100, + kExpectedMetaData.size() + 1)); + sender.PushBody(kExpectedBody); + sender.PushMetaData(kExpectedMetaData); + // GetRawScriptData should be blocked until body and meta data transfer are + // finished. + EXPECT_FALSE(get_raw_script_data_waiter->IsSignaled()); + sender.FinishTransferBody(); + sender.FinishTransferMetaData(); + + // Wait for the script's arrival. + get_raw_script_data_waiter->Wait(); + // |script_data| should be nullptr since the data pipe for body gets + // disconnected during sending. + EXPECT_FALSE(script_data); + } + + { + std::unique_ptr<RawScriptData> script_data; + GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data)->Wait(); + // This should not be blocked because the script won't arrive. nullptr will + // be returned after disconnection. + EXPECT_EQ(nullptr, script_data.get()); + } +} + +TEST_F(WebServiceWorkerInstalledScriptsManagerImplTest, + EarlyDisconnectionMetaData) { + const GURL kScriptUrl = GURL("https://example.com/installed1.js"); + const GURL kUnknownScriptUrl = GURL("https://example.com/not_installed.js"); + + BrowserSideSender sender({kScriptUrl}); + CreateInstalledScriptsManager(sender.CreateAndBind()); + + { + std::unique_ptr<RawScriptData> script_data; + const std::string kExpectedBody = "This is a script body."; + const std::string kExpectedMetaData = "This is a meta data."; + base::WaitableEvent* get_raw_script_data_waiter = + GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data); + + // Start transferring the script. + // Meta data is expected to be 100 bytes larger than kExpectedMetaData, but + // sender only sends kExpectedBody and a null byte (kExpectedMetaData.size() + // + 1 bytes in total). + EXPECT_EQ(kScriptUrl, + sender.TransferInstalledScript(kExpectedBody.size() + 1, + kExpectedMetaData.size() + 100)); + sender.PushBody(kExpectedBody); + sender.PushMetaData(kExpectedMetaData); + // GetRawScriptData should be blocked until body and meta data transfer are + // finished. + EXPECT_FALSE(get_raw_script_data_waiter->IsSignaled()); + sender.FinishTransferBody(); + sender.FinishTransferMetaData(); + + // Wait for the script's arrival. + get_raw_script_data_waiter->Wait(); + // |script_data| should be nullptr since the data pipe for body gets + // disconnected during sending. + EXPECT_FALSE(script_data); + } + + { + std::unique_ptr<RawScriptData> script_data; + GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data)->Wait(); + // This should not be blocked because the script won't arrive. nullptr will + // be returned after disconnection. + EXPECT_EQ(nullptr, script_data.get()); + } +} + +TEST_F(WebServiceWorkerInstalledScriptsManagerImplTest, + EarlyDisconnectionManager) { + const GURL kScriptUrl = GURL("https://example.com/installed1.js"); + const GURL kUnknownScriptUrl = GURL("https://example.com/not_installed.js"); + + BrowserSideSender sender({kScriptUrl}); + CreateInstalledScriptsManager(sender.CreateAndBind()); + + { + std::unique_ptr<RawScriptData> script_data; + base::WaitableEvent* get_raw_script_data_waiter = + GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data); + + // Reset the Mojo connection before sending the script. + EXPECT_FALSE(get_raw_script_data_waiter->IsSignaled()); + sender.ResetManager(); + + // Wait for the script's arrival. + get_raw_script_data_waiter->Wait(); + // |script_data| should be nullptr since no data will arrive. + EXPECT_FALSE(script_data); + } + + { + std::unique_ptr<RawScriptData> script_data; + GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data)->Wait(); + // This should not be blocked because data will not arrive anymore. EXPECT_EQ(nullptr, script_data.get()); } }
diff --git a/content/test/data/devtools/enable_touch.html b/content/test/data/devtools/enable_touch.html new file mode 100644 index 0000000..74b64bd --- /dev/null +++ b/content/test/data/devtools/enable_touch.html
@@ -0,0 +1,13 @@ +<script> +function checkProtos(expect) { + var allMatch = true; + for (var obj of [window, Document.prototype, HTMLElement.prototype, SVGElement.prototype]) { + for (var prop of ['ontouchstart', 'ontouchend', 'ontouchmove', 'ontouchcancel']) { + var result = prop in obj; + if (result !== expect) + allMatch = false; + } + } + return allMatch; +} +</script> \ No newline at end of file
diff --git a/docs/README.md b/docs/README.md index 3ab2f4b..d13126d5 100644 --- a/docs/README.md +++ b/docs/README.md
@@ -133,6 +133,8 @@ more performant * [ES6 Support in Chromium](es6_chromium.md) - Implementation of ECMAScript6 features in Chromium +* [Adding a new feature flag in chrome://flags](how_to_add_your_feature_flag.md) - Quick + guide to add a new feature flag to experiment your feature. ### Testing * [Running and Debugging Layout Tests](testing/layout_tests.md)
diff --git a/docs/how_to_add_your_feature_flag.md b/docs/how_to_add_your_feature_flag.md new file mode 100644 index 0000000..a80f1e6 --- /dev/null +++ b/docs/how_to_add_your_feature_flag.md
@@ -0,0 +1,53 @@ +# Adding a new feature flag in chrome://flags + +This document describes how to add your new feature behind a flag. + +## Step 1: Adding a new `base::Feature` +This step would be different between where you want to use the flag. +For example, if you want to use the flag in src/content, you should add a base::Feature to the following files: + +* [content/public/common/content_features.cc](https://cs.chromium.org/chromium/src/content/public/common/content_features.cc) +* [content/public/common/content_features.h](https://cs.chromium.org/chromium/src/content/public/common/content_features.h) + +If you want to use the flag in blink, you should also read +[Runtime Enable Features](https://www.chromium.org/blink/runtime-enabled-features). + +You can refer to [this CL](https://chromium-review.googlesource.com/c/554510/) +to see + +1. where to add the base::Feature +[[1](https://chromium-review.googlesource.com/c/554510/8/content/public/common/content_features.cc#253)] +[[2](https://chromium-review.googlesource.com/c/554510/8/content/public/common/content_features.h)] +2. how to use it +[[1](https://chromium-review.googlesource.com/c/554510/8/content/common/service_worker/service_worker_utils.cc#153)] +3. how to wire the base::Feature to WebRuntimeFeatures +[[1](https://chromium-review.googlesource.com/c/554510/8/content/child/runtime_features.cc)] +[[2](https://chromium-review.googlesource.com/c/554510/8/third_party/WebKit/public/platform/WebRuntimeFeatures.h)] +[[3](https://chromium-review.googlesource.com/c/554510/third_party/WebKit/Source/platform/exported/WebRuntimeFeatures.cpp)] +[[4](https://chromium-review.googlesource.com/c/554510/8/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5)] +4. how to use it in blink +[[1](https://chromium-review.googlesource.com/c/554510/8/third_party/WebKit/Source/core/workers/WorkerThread.cpp)] + +Also, this patch added a virtual test for running layout tests with the flag. +When you add a flag, you can consider to use that. + +## Step 2: Adding the feature flag to the chrome://flags UI. +You have to modify these four files in total. + +* [chrome/browser/about_flags.cc](https://cs.chromium.org/chromium/src/chrome/browser/about_flags.cc) +* [chrome/browser/flag_descriptions.cc](https://cs.chromium.org/chromium/src/chrome/browser/flag_descriptions.cc) +* [chrome/browser/flag_descriptions.h](https://cs.chromium.org/chromium/src/chrome/browser/flag_descriptions.h) +* [tools/metrics/histograms/enums.xml](https://cs.chromium.org/chromium/src/tools/metrics/histograms/enums.xml) + +At first you need to add an entry to __about_flags.cc__, +__flag_descriptions.cc__ and __flag_descriptions.h__. After that, try running the following test. + +```bash +# Build unit_tests +ninja -C out/Default unit_tests +# Run AboutFlagsHistogramTest.CheckHistograms +./out/Default/unit_tests --gtest_filter=AboutFlagsHistogramTest.CheckHistograms +``` + +That test will ask you to add several entries to enums.xml. +You can refer to [this CL](https://chromium-review.googlesource.com/c/593707) as an example.
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index 5b68377..ce93d49e 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -150,6 +150,7 @@ void FreePendingToken(void* p, unsigned int /* token */) override; unsigned int GetSize() const override; unsigned int GetFreeSize() const override; + void ShrinkLastBlock(unsigned int new_size) override; size_t MaxTransferBufferSize() { return size_ - result_size_; @@ -334,6 +335,8 @@ return 0; } +void MockTransferBuffer::ShrinkLastBlock(unsigned int new_size) {} + // API wrapper for Buffers. class GenBuffersAPI { public:
diff --git a/gpu/command_buffer/client/ring_buffer.cc b/gpu/command_buffer/client/ring_buffer.cc index 118dc57..8ce77e9 100644 --- a/gpu/command_buffer/client/ring_buffer.cc +++ b/gpu/command_buffer/client/ring_buffer.cc
@@ -179,4 +179,18 @@ } } +void RingBuffer::ShrinkLastBlock(unsigned int new_size) { + if (blocks_.empty()) + return; + auto& block = blocks_.back(); + DCHECK_LT(new_size, block.size); + DCHECK_EQ(block.state, IN_USE); + + // Can't shrink to size 0, see comments in Alloc. + new_size = std::max(new_size, 1u); + + free_offset_ = block.offset + new_size; + block.size = new_size; +} + } // namespace gpu
diff --git a/gpu/command_buffer/client/ring_buffer.h b/gpu/command_buffer/client/ring_buffer.h index 083cb01..48ba789 100644 --- a/gpu/command_buffer/client/ring_buffer.h +++ b/gpu/command_buffer/client/ring_buffer.h
@@ -90,6 +90,9 @@ return (size + alignment_ - 1) & ~(alignment_ - 1); } + // Shrinks the last block. new_size must be smaller than the current size + // and the block must still be in use in order to shrink. + void ShrinkLastBlock(unsigned int new_size); private: enum State {
diff --git a/gpu/command_buffer/client/transfer_buffer.cc b/gpu/command_buffer/client/transfer_buffer.cc index 0aa21049..7a35999c 100644 --- a/gpu/command_buffer/client/transfer_buffer.cc +++ b/gpu/command_buffer/client/transfer_buffer.cc
@@ -105,6 +105,10 @@ return HaveBuffer() ? ring_buffer_->GetTotalFreeSizeNoWaiting() : 0; } +void TransferBuffer::ShrinkLastBlock(unsigned int new_size) { + ring_buffer_->ShrinkLastBlock(new_size); +} + void TransferBuffer::AllocateRingBuffer(unsigned int size) { for (;size >= min_buffer_size_; size /= 2) { int32_t id = -1; @@ -230,4 +234,11 @@ buffer_ = transfer_buffer_->AllocUpTo(new_size, &size_); } +void ScopedTransferBufferPtr::Shrink(unsigned int new_size) { + if (!transfer_buffer_->HaveBuffer() || new_size >= size_) + return; + transfer_buffer_->ShrinkLastBlock(new_size); + size_ = new_size; +} + } // namespace gpu
diff --git a/gpu/command_buffer/client/transfer_buffer.h b/gpu/command_buffer/client/transfer_buffer.h index 155e8b0..fda4ac2 100644 --- a/gpu/command_buffer/client/transfer_buffer.h +++ b/gpu/command_buffer/client/transfer_buffer.h
@@ -69,6 +69,8 @@ virtual unsigned int GetSize() const = 0; virtual unsigned int GetFreeSize() const = 0; + + virtual void ShrinkLastBlock(unsigned int new_size) = 0; }; // Class that manages the transfer buffer. @@ -97,6 +99,7 @@ void FreePendingToken(void* p, unsigned int token) override; unsigned int GetSize() const override; unsigned int GetFreeSize() const override; + void ShrinkLastBlock(unsigned int new_size) override; // These are for testing. unsigned int GetCurrentMaxAllocationWithoutRealloc() const; @@ -200,6 +203,9 @@ void Reset(unsigned int new_size); + // Shrinks this transfer buffer to a given size. + void Shrink(unsigned int new_size); + private: void* buffer_; unsigned int size_;
diff --git a/gpu/command_buffer/client/transfer_buffer_unittest.cc b/gpu/command_buffer/client/transfer_buffer_unittest.cc index bb67d53d..550959f 100644 --- a/gpu/command_buffer/client/transfer_buffer_unittest.cc +++ b/gpu/command_buffer/client/transfer_buffer_unittest.cc
@@ -505,4 +505,34 @@ transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc()); } +TEST_F(TransferBufferExpandContractTest, Shrink) { + unsigned int alloc_size = transfer_buffer_->GetFreeSize(); + EXPECT_EQ(kStartTransferBufferSize - kStartingOffset, alloc_size); + unsigned int size_allocated = 0; + void* ptr = transfer_buffer_->AllocUpTo(alloc_size, &size_allocated); + + ASSERT_NE(ptr, nullptr); + EXPECT_EQ(alloc_size, size_allocated); + EXPECT_GT(alloc_size, 0u); + EXPECT_EQ(0u, transfer_buffer_->GetFreeSize()); + + // Shrink once. + const unsigned int shrink_size1 = 80; + EXPECT_LT(shrink_size1, alloc_size); + transfer_buffer_->ShrinkLastBlock(shrink_size1); + EXPECT_EQ(alloc_size - shrink_size1, transfer_buffer_->GetFreeSize()); + + // Shrink again. + const unsigned int shrink_size2 = 30; + EXPECT_LT(shrink_size2, shrink_size1); + transfer_buffer_->ShrinkLastBlock(shrink_size2); + EXPECT_EQ(alloc_size - shrink_size2, transfer_buffer_->GetFreeSize()); + + // Shrink to zero (minimum size is 1). + transfer_buffer_->ShrinkLastBlock(0); + EXPECT_EQ(alloc_size - 1, transfer_buffer_->GetFreeSize()); + + transfer_buffer_->FreePendingToken(ptr, 1); +} + } // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 2f09ce9..0df37b0 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -2832,8 +2832,19 @@ scoped_refptr<gl::GLImage> image = decoder_->GetContextGroup()->image_factory()->CreateAnonymousImage( size, - format == GL_RGB ? gfx::BufferFormat::RGBX_8888 - : gfx::BufferFormat::RGBA_8888, + format == GL_RGB + ? +#if defined(USE_OZONE) + // BGRX format is preferred for Ozone as it matches the format + // used by the buffer queue and is as a result guaranteed to work + // on all devices. + // TODO(reveman): Define this format in one place instead of + // having to duplicate BGRX_8888. + gfx::BufferFormat::BGRX_8888 +#else + gfx::BufferFormat::RGBX_8888 +#endif + : gfx::BufferFormat::RGBA_8888, format); if (!image || !image->BindTexImage(Target())) return false;
diff --git a/headless/BUILD.gn b/headless/BUILD.gn index b27bf3b..0b15edd 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn
@@ -223,7 +223,7 @@ extra_deps = [ ":gen_devtools_client_api" ] } -if (headless_fontconfig_utils) { +if (headless_fontconfig_utils && !is_fuchsia) { static_library("headless_fontconfig_utils") { sources = [ "public/util/fontconfig.cc",
diff --git a/ios/chrome/browser/content_suggestions/BUILD.gn b/ios/chrome/browser/content_suggestions/BUILD.gn index e4c37000..fea6bbf 100644 --- a/ios/chrome/browser/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/content_suggestions/BUILD.gn
@@ -78,29 +78,3 @@ ] configs += [ "//build/config/compiler:enable_arc" ] } - -source_set("eg_tests") { - configs += [ "//build/config/compiler:enable_arc" ] - testonly = true - sources = [ - "content_suggestions_alert_egtest.mm", - ] - deps = [ - ":content_suggestions", - "//base", - "//base/test:test_support", - "//ios/chrome/app/strings", - "//ios/chrome/browser/ui", - "//ios/chrome/browser/ui/alert_coordinator", - "//ios/chrome/browser/ui/alert_coordinator", - "//ios/chrome/browser/ui/collection_view/cells", - "//ios/chrome/browser/ui/content_suggestions/cells", - "//ios/chrome/browser/ui/util", - "//ios/chrome/test/earl_grey:test_support", - "//ui/strings", - ] - libs = [ - "UIKit.framework", - "XCTest.framework", - ] -}
diff --git a/ios/chrome/browser/content_suggestions/content_suggestions_alert_egtest.mm b/ios/chrome/browser/content_suggestions/content_suggestions_alert_egtest.mm deleted file mode 100644 index a1942a6b7..0000000 --- a/ios/chrome/browser/content_suggestions/content_suggestions_alert_egtest.mm +++ /dev/null
@@ -1,99 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/content_suggestions/content_suggestions_alert_factory.h" - -#import <EarlGrey/EarlGrey.h> -#import <XCTest/XCTest.h> - -#import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" -#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_gesture_commands.h" -#include "ios/chrome/browser/ui/ui_util.h" -#import "ios/chrome/browser/ui/util/top_view_controller.h" -#include "ios/chrome/grit/ios_strings.h" -#import "ios/chrome/test/earl_grey/chrome_matchers.h" -#import "ios/chrome/test/earl_grey/chrome_test_case.h" -#include "ui/strings/grit/ui_strings.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface ContentSuggestionsAlertFactoryTestCase : XCTestCase - -@end - -@implementation ContentSuggestionsAlertFactoryTestCase - -- (void)testSuggestionsAlert { - UIViewController* viewController = - top_view_controller::TopPresentedViewController(); - AlertCoordinator* coordinator = [ContentSuggestionsAlertFactory - alertCoordinatorForSuggestionItem:nil - onViewController:viewController - atPoint:CGPointMake(50, 50) - atIndexPath:nil - readLaterAction:YES - commandHandler:nil]; - [coordinator start]; - - [[EarlGrey - selectElementWithMatcher:chrome_test_util::ButtonWithAccessibilityLabelId( - IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB)] - assertWithMatcher:grey_interactable()]; - [[EarlGrey selectElementWithMatcher: - chrome_test_util::ButtonWithAccessibilityLabelId( - IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB)] - assertWithMatcher:grey_interactable()]; - [[EarlGrey - selectElementWithMatcher:chrome_test_util::ButtonWithAccessibilityLabelId( - IDS_IOS_CONTENT_SUGGESTIONS_REMOVE)] - assertWithMatcher:grey_interactable()]; - [[EarlGrey - selectElementWithMatcher:chrome_test_util::ButtonWithAccessibilityLabelId( - IDS_IOS_CONTENT_CONTEXT_ADDTOREADINGLIST)] - assertWithMatcher:grey_interactable()]; - if (!IsIPadIdiom()) { - [[EarlGrey selectElementWithMatcher: - chrome_test_util::ButtonWithAccessibilityLabelId( - IDS_APP_CANCEL)] assertWithMatcher:grey_interactable()]; - } - - [coordinator stop]; -} - -- (void)testMostVisitedAlert { - UIViewController* viewController = - top_view_controller::TopPresentedViewController(); - AlertCoordinator* coordinator = [ContentSuggestionsAlertFactory - alertCoordinatorForMostVisitedItem:nil - onViewController:viewController - atPoint:CGPointMake(50, 50) - atIndexPath:nil - commandHandler:nil]; - [coordinator start]; - - [[EarlGrey - selectElementWithMatcher:chrome_test_util::ButtonWithAccessibilityLabelId( - IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB)] - assertWithMatcher:grey_interactable()]; - [[EarlGrey selectElementWithMatcher: - chrome_test_util::ButtonWithAccessibilityLabelId( - IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB)] - assertWithMatcher:grey_interactable()]; - [[EarlGrey - selectElementWithMatcher:chrome_test_util::ButtonWithAccessibilityLabelId( - IDS_IOS_CONTENT_SUGGESTIONS_REMOVE)] - assertWithMatcher:grey_interactable()]; - if (!IsIPadIdiom()) { - [[EarlGrey selectElementWithMatcher: - chrome_test_util::ButtonWithAccessibilityLabelId( - IDS_APP_CANCEL)] assertWithMatcher:grey_interactable()]; - } - - [coordinator stop]; -} - -@end
diff --git a/ios/chrome/browser/content_suggestions/content_suggestions_alert_factory.h b/ios/chrome/browser/content_suggestions/content_suggestions_alert_factory.h index 2b51a0d5..c9798ade 100644 --- a/ios/chrome/browser/content_suggestions/content_suggestions_alert_factory.h +++ b/ios/chrome/browser/content_suggestions/content_suggestions_alert_factory.h
@@ -17,12 +17,12 @@ // Returns an AlertCoordinator for a suggestions |item| with the indexPath // |indexPath|. The alert will be presented on the |viewController| at the -// |touchLocation|, in the coordinates of the |viewController|'s view. The -// |commandHandler| will receive callbacks when the user chooses one of the +// |touchLocation|, in the coordinates of the |viewController|'s collectionView. +// The |commandHandler| will receive callbacks when the user chooses one of the // options displayed by the alert. + (AlertCoordinator*) alertCoordinatorForSuggestionItem:(ContentSuggestionsItem*)item - onViewController:(UIViewController*)viewController + onViewController:(UICollectionViewController*)viewController atPoint:(CGPoint)touchLocation atIndexPath:(NSIndexPath*)indexPath readLaterAction:(BOOL)readLaterAction @@ -32,7 +32,7 @@ // Same as above but for a MostVisited item. + (AlertCoordinator*) alertCoordinatorForMostVisitedItem:(ContentSuggestionsMostVisitedItem*)item - onViewController:(UIViewController*)viewController + onViewController:(UICollectionViewController*)viewController atPoint:(CGPoint)touchLocation atIndexPath:(NSIndexPath*)indexPath commandHandler:
diff --git a/ios/chrome/browser/content_suggestions/content_suggestions_alert_factory.mm b/ios/chrome/browser/content_suggestions/content_suggestions_alert_factory.mm index dcec6e0..c83b22c0 100644 --- a/ios/chrome/browser/content_suggestions/content_suggestions_alert_factory.mm +++ b/ios/chrome/browser/content_suggestions/content_suggestions_alert_factory.mm
@@ -20,7 +20,7 @@ + (AlertCoordinator*) alertCoordinatorForSuggestionItem:(ContentSuggestionsItem*)item - onViewController:(UIViewController*)viewController + onViewController:(UICollectionViewController*)viewController atPoint:(CGPoint)touchLocation atIndexPath:(NSIndexPath*)indexPath readLaterAction:(BOOL)readLaterAction @@ -32,7 +32,7 @@ message:nil rect:CGRectMake(touchLocation.x, touchLocation.y, 0, 0) - view:[viewController view]]; + view:viewController.collectionView]; __weak ContentSuggestionsItem* weakItem = item; __weak id<ContentSuggestionsGestureCommands> weakCommandHandler = @@ -105,7 +105,7 @@ + (AlertCoordinator*) alertCoordinatorForMostVisitedItem:(ContentSuggestionsMostVisitedItem*)item - onViewController:(UIViewController*)viewController + onViewController:(UICollectionViewController*)viewController atPoint:(CGPoint)touchLocation atIndexPath:(NSIndexPath*)indexPath commandHandler: @@ -116,7 +116,7 @@ message:nil rect:CGRectMake(touchLocation.x, touchLocation.y, 0, 0) - view:[viewController view]]; + view:viewController.collectionView]; __weak ContentSuggestionsMostVisitedItem* weakItem = item; __weak id<ContentSuggestionsGestureCommands> weakCommandHandler =
diff --git a/ios/chrome/browser/payments/payment_response_helper.mm b/ios/chrome/browser/payments/payment_response_helper.mm index d108430d..9535010 100644 --- a/ios/chrome/browser/payments/payment_response_helper.mm +++ b/ios/chrome/browser/payments/payment_response_helper.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/payments/payment_response_helper.h" #include "base/bind.h" +#include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/autofill_country.h" #include "components/autofill/core/browser/autofill_type.h" @@ -67,8 +68,9 @@ response.details = stringified_details_; if (payment_request_->request_shipping()) { - response.shipping_address = data_util::GetPaymentAddressFromAutofillProfile( - shipping_address_, payment_request_->GetApplicationLocale()); + response.shipping_address = base::MakeUnique<payments::PaymentAddress>( + data_util::GetPaymentAddressFromAutofillProfile( + shipping_address_, payment_request_->GetApplicationLocale())); web::PaymentShippingOption* shippingOption = payment_request_->selected_shipping_option();
diff --git a/ios/chrome/browser/payments/payment_response_helper_unittest.mm b/ios/chrome/browser/payments/payment_response_helper_unittest.mm index 23fc7d5d..1cc2d814 100644 --- a/ios/chrome/browser/payments/payment_response_helper_unittest.mm +++ b/ios/chrome/browser/payments/payment_response_helper_unittest.mm
@@ -116,27 +116,29 @@ EXPECT_EQ(GetMethodName(), response.method_name); EXPECT_EQ(GetStringifiedDetails(), response.details); - EXPECT_EQ(base::ASCIIToUTF16("US"), response.shipping_address.country); - ASSERT_EQ(2U, response.shipping_address.address_line.size()); + EXPECT_TRUE(!!response.shipping_address); + EXPECT_EQ(base::ASCIIToUTF16("US"), + response.shipping_address->country); + ASSERT_EQ(2U, response.shipping_address->address_line.size()); EXPECT_EQ(base::ASCIIToUTF16("666 Erebus St."), - response.shipping_address.address_line[0]); + response.shipping_address->address_line[0]); EXPECT_EQ(base::ASCIIToUTF16("Apt 8"), - response.shipping_address.address_line[1]); - EXPECT_EQ(base::ASCIIToUTF16("CA"), response.shipping_address.region); + response.shipping_address->address_line[1]); + EXPECT_EQ(base::ASCIIToUTF16("CA"), response.shipping_address->region); EXPECT_EQ(base::ASCIIToUTF16("Elysium"), - response.shipping_address.city); + response.shipping_address->city); EXPECT_EQ(base::string16(), - response.shipping_address.dependent_locality); + response.shipping_address->dependent_locality); EXPECT_EQ(base::ASCIIToUTF16("91111"), - response.shipping_address.postal_code); - EXPECT_EQ(base::string16(), response.shipping_address.sorting_code); - EXPECT_EQ(base::string16(), response.shipping_address.language_code); + response.shipping_address->postal_code); + EXPECT_EQ(base::string16(), response.shipping_address->sorting_code); + EXPECT_EQ(base::string16(), response.shipping_address->language_code); EXPECT_EQ(base::ASCIIToUTF16("Underworld"), - response.shipping_address.organization); + response.shipping_address->organization); EXPECT_EQ(base::ASCIIToUTF16("John H. Doe"), - response.shipping_address.recipient); + response.shipping_address->recipient); EXPECT_EQ(base::ASCIIToUTF16("16502111111"), - response.shipping_address.phone); + response.shipping_address->phone); EXPECT_EQ(base::ASCIIToUTF16("John H. Doe"), response.payer_name); EXPECT_EQ(base::ASCIIToUTF16("+16502111111"), response.payer_phone); @@ -162,19 +164,7 @@ @selector(paymentResponseHelperDidCompleteWithPaymentResponse:); [consumer_mock onSelector:selector callBlockExpectation:^(const web::PaymentResponse& response) { - EXPECT_EQ(base::string16(), response.shipping_address.country); - EXPECT_TRUE(response.shipping_address.address_line.empty()); - EXPECT_EQ(base::string16(), response.shipping_address.region); - EXPECT_EQ(base::string16(), response.shipping_address.city); - EXPECT_EQ(base::string16(), - response.shipping_address.dependent_locality); - EXPECT_EQ(base::string16(), response.shipping_address.postal_code); - EXPECT_EQ(base::string16(), response.shipping_address.sorting_code); - EXPECT_EQ(base::string16(), response.shipping_address.language_code); - EXPECT_EQ(base::string16(), response.shipping_address.organization); - EXPECT_EQ(base::string16(), response.shipping_address.recipient); - EXPECT_EQ(base::string16(), response.shipping_address.phone); - + EXPECT_FALSE(!!response.shipping_address); EXPECT_EQ(base::ASCIIToUTF16("John H. Doe"), response.payer_name); EXPECT_EQ(base::ASCIIToUTF16("+16502111111"), response.payer_phone); EXPECT_EQ(base::ASCIIToUTF16("johndoe@hades.com"),
diff --git a/ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.h b/ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.h index 0d39c1d..2cdf2c2 100644 --- a/ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.h +++ b/ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.h
@@ -9,6 +9,8 @@ #import "ios/chrome/browser/ui/collection_view/collection_view_controller.h" +extern NSString* const kSigninConfirmationCollectionViewId; + @class ChromeIdentity; @class SigninConfirmationViewController;
diff --git a/ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.mm b/ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.mm index f618bd01..1c512b5 100644 --- a/ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.mm
@@ -34,6 +34,9 @@ #error "This file requires ARC support." #endif +NSString* const kSigninConfirmationCollectionViewId = + @"SigninConfirmationCollectionView"; + namespace { const CGFloat kAccountImageDimension = 64.; const CGFloat kHeaderViewMinHeight = 170.; @@ -114,6 +117,7 @@ - (void)viewDidLoad { [super viewDidLoad]; + self.view.accessibilityIdentifier = kSigninConfirmationCollectionViewId; // Configure the header. MDCFlexibleHeaderView* headerView =
diff --git a/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm b/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm index 5fda35c..4436692 100644 --- a/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm +++ b/ios/chrome/browser/ui/authentication/signin_interaction_controller_egtest.mm
@@ -5,7 +5,6 @@ #import <EarlGrey/EarlGrey.h> #import <XCTest/XCTest.h> -#include "base/ios/ios_util.h" #include "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h" #include "components/signin/core/browser/signin_manager.h" @@ -87,13 +86,6 @@ [[EarlGrey selectElementWithMatcher:matcher] performAction:grey_tap()]; } -// Opens the signin screen from the settings page. Must be called from the NTP. -// User must not be signed in. -void OpenSignInFromSettings() { - [ChromeEarlGreyUI openSettingsMenu]; - TapViewWithAccessibilityId(kSettingsSignInCellId); -} - // Wait until |matcher| is accessible (not nil) void WaitForMatcher(id<GREYMatcher> matcher) { ConditionBlock condition = ^{ @@ -132,26 +124,15 @@ // Tests that opening the sign-in screen from the Settings and signing in works // correctly when there is already an identity on the device. - (void)testSignInOneUser { - // TODO(crbug.com/747444): Re-enable this test on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11."); - } - // Set up a fake identity. ChromeIdentity* identity = GetFakeIdentity1(); ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()->AddIdentity( identity); - // Open the sign in screen. - OpenSignInFromSettings(); - - // Select the user. - TapButtonWithAccessibilityLabel(identity.userEmail); - - // Sign in and confirm. - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON); - + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SignInMenuButton()]; + [ChromeEarlGreyUI signInToIdentityByEmail:identity.userEmail]; + [ChromeEarlGreyUI confirmSigninConfirmationDialog]; [[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()] performAction:grey_tap()]; @@ -162,11 +143,6 @@ // Tests signing in with one account, switching sync account to a second and // choosing to keep the browsing data separate during the switch. - (void)testSignInSwitchAccountsAndKeepDataSeparate { - // TODO(crbug.com/747444): Re-enable this test on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11."); - } - // Set up the fake identities. ios::FakeChromeIdentityService* identity_service = ios::FakeChromeIdentityService::GetInstanceFromChromeProvider(); @@ -175,11 +151,10 @@ identity_service->AddIdentity(identity1); identity_service->AddIdentity(identity2); - // Sign in to |identity1|. - OpenSignInFromSettings(); - TapButtonWithAccessibilityLabel(identity1.userEmail); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON); + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SignInMenuButton()]; + [ChromeEarlGreyUI signInToIdentityByEmail:identity1.userEmail]; + [ChromeEarlGreyUI confirmSigninConfirmationDialog]; AssertAuthenticatedIdentityInActiveProfile(identity1); // Open accounts settings, then sync settings. @@ -189,12 +164,8 @@ // Switch Sync account to |identity2|. TapButtonWithAccessibilityLabel(identity2.userEmail); - // Keep data separate, with synchronization off due to an infinite spinner. - SetEarlGreySynchronizationEnabled(NO); - WaitForMatcher(grey_accessibilityID(kImportDataKeepSeparateCellId)); TapViewWithAccessibilityId(kImportDataKeepSeparateCellId); TapButtonWithLabelId(IDS_IOS_OPTIONS_IMPORT_DATA_CONTINUE_BUTTON); - SetEarlGreySynchronizationEnabled(YES); // Check the signed-in user did change. AssertAuthenticatedIdentityInActiveProfile(identity2); @@ -206,11 +177,6 @@ // Tests signing in with one account, switching sync account to a second and // choosing to import the browsing data during the switch. - (void)testSignInSwitchAccountsAndImportData { - // TODO(crbug.com/747444): Re-enable this test on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11."); - } - // Set up the fake identities. ios::FakeChromeIdentityService* identity_service = ios::FakeChromeIdentityService::GetInstanceFromChromeProvider(); @@ -220,10 +186,10 @@ identity_service->AddIdentity(identity2); // Sign in to |identity1|. - OpenSignInFromSettings(); - TapButtonWithAccessibilityLabel(identity1.userEmail); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON); + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SignInMenuButton()]; + [ChromeEarlGreyUI signInToIdentityByEmail:identity1.userEmail]; + [ChromeEarlGreyUI confirmSigninConfirmationDialog]; AssertAuthenticatedIdentityInActiveProfile(identity1); // Open accounts settings, then sync settings. @@ -233,12 +199,8 @@ // Switch Sync account to |identity2|. TapButtonWithAccessibilityLabel(identity2.userEmail); - // Import data, with synchronization off due to an infinite spinner. - SetEarlGreySynchronizationEnabled(NO); - WaitForMatcher(grey_accessibilityID(kImportDataImportCellId)); TapViewWithAccessibilityId(kImportDataImportCellId); TapButtonWithLabelId(IDS_IOS_OPTIONS_IMPORT_DATA_CONTINUE_BUTTON); - SetEarlGreySynchronizationEnabled(YES); // Check the signed-in user did change. AssertAuthenticatedIdentityInActiveProfile(identity2); @@ -250,11 +212,6 @@ // Tests that switching from a managed account to a non-managed account works // correctly and displays the expected warnings. - (void)testSignInSwitchManagedAccount { - // TODO(crbug.com/747444): Re-enable this test on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11."); - } - if (!experimental_flags::IsMDMIntegrationEnabled()) { EARL_GREY_TEST_SKIPPED(@"Only enabled with MDM integration."); } @@ -267,10 +224,9 @@ identity_service->AddIdentity(managed_identity); identity_service->AddIdentity(identity); - // Sign in to |managed_identity|. - OpenSignInFromSettings(); - TapButtonWithAccessibilityLabel(managed_identity.userEmail); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON); + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SignInMenuButton()]; + [ChromeEarlGreyUI signInToIdentityByEmail:managed_identity.userEmail]; // Accept warning for signing into a managed identity, with synchronization // off due to an infinite spinner. @@ -280,7 +236,7 @@ TapButtonWithLabelId(IDS_IOS_MANAGED_SIGNIN_ACCEPT_BUTTON); SetEarlGreySynchronizationEnabled(YES); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON); + [ChromeEarlGreyUI confirmSigninConfirmationDialog]; AssertAuthenticatedIdentityInActiveProfile(managed_identity); // Switch Sync account to |identity|. @@ -288,8 +244,6 @@ TapViewWithAccessibilityId(kSettingsAccountsSyncCellId); TapButtonWithAccessibilityLabel(identity.userEmail); - // Accept warning for signout out of a managed identity, with synchronization - // off due to an infinite spinner. SetEarlGreySynchronizationEnabled(NO); WaitForMatcher(chrome_test_util::ButtonWithAccessibilityLabelId( IDS_IOS_MANAGED_SWITCH_ACCEPT_BUTTON)); @@ -304,20 +258,15 @@ // Tests that signing out from the Settings works correctly. - (void)testSignInDisconnectFromChrome { - // TODO(crbug.com/747444): Re-enable this test on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11."); - } - ChromeIdentity* identity = GetFakeIdentity1(); ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()->AddIdentity( identity); // Sign in to |identity|. - OpenSignInFromSettings(); - TapButtonWithAccessibilityLabel(identity.userEmail); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON); + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SignInMenuButton()]; + [ChromeEarlGreyUI signInToIdentityByEmail:identity.userEmail]; + [ChromeEarlGreyUI confirmSigninConfirmationDialog]; AssertAuthenticatedIdentityInActiveProfile(identity); // Go to Accounts Settings and tap the sign out button. @@ -331,9 +280,6 @@ performAction:grey_tap()]; TapButtonWithLabelId(IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE); - // Check that the settings home screen is shown. - WaitForMatcher(grey_accessibilityID(kSettingsSignInCellId)); - [[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()] performAction:grey_tap()]; @@ -344,11 +290,6 @@ // Tests that signing out of a managed account from the Settings works // correctly. - (void)testSignInDisconnectFromChromeManaged { - // TODO(crbug.com/747444): Re-enable this test on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11."); - } - if (!experimental_flags::IsMDMIntegrationEnabled()) { EARL_GREY_TEST_SKIPPED(@"Only enabled with MDM integration."); } @@ -357,17 +298,18 @@ ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()->AddIdentity( identity); - // Sign in to |identity|. - OpenSignInFromSettings(); - TapButtonWithAccessibilityLabel(identity.userEmail); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON); + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SignInMenuButton()]; + [ChromeEarlGreyUI signInToIdentityByEmail:identity.userEmail]; + // Synchronization off due to an infinite spinner. SetEarlGreySynchronizationEnabled(NO); WaitForMatcher(chrome_test_util::ButtonWithAccessibilityLabelId( IDS_IOS_MANAGED_SIGNIN_ACCEPT_BUTTON)); TapButtonWithLabelId(IDS_IOS_MANAGED_SIGNIN_ACCEPT_BUTTON); SetEarlGreySynchronizationEnabled(YES); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON); + + [ChromeEarlGreyUI confirmSigninConfirmationDialog]; AssertAuthenticatedIdentityInActiveProfile(identity); // Go to Accounts Settings and tap the sign out button. @@ -381,9 +323,6 @@ performAction:grey_tap()]; TapButtonWithLabelId(IDS_IOS_MANAGED_DISCONNECT_DIALOG_ACCEPT); - // Check that the settings home screen is shown. - WaitForMatcher(grey_accessibilityID(kSettingsSignInCellId)); - [[EarlGrey selectElementWithMatcher:NavigationBarDoneButton()] performAction:grey_tap()]; @@ -399,15 +338,13 @@ ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()->AddIdentity( identity); - // Sign in to |identity|. - OpenSignInFromSettings(); - TapButtonWithAccessibilityLabel(identity.userEmail); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON); + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SignInMenuButton()]; + [ChromeEarlGreyUI signInToIdentityByEmail:identity.userEmail]; // Tap Settings link. id<GREYMatcher> settings_link_matcher = grey_allOf( grey_accessibilityLabel(@"Settings"), grey_sufficientlyVisible(), nil); - WaitForMatcher(settings_link_matcher); [[EarlGrey selectElementWithMatcher:settings_link_matcher] performAction:grey_tap()]; @@ -432,7 +369,8 @@ ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()->AddIdentity( identity); - OpenSignInFromSettings(); + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SignInMenuButton()]; // Open new tab to cancel sign-in. OpenUrlCommand* command = @@ -441,7 +379,8 @@ // Re-open the sign-in screen. If it wasn't correctly dismissed previously, // this will fail. - OpenSignInFromSettings(); + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SignInMenuButton()]; id<GREYMatcher> signin_matcher = chrome_test_util::StaticTextWithAccessibilityLabelId( IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_DESCRIPTION); @@ -463,7 +402,8 @@ ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()->AddIdentity( identity); - OpenSignInFromSettings(); + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SignInMenuButton()]; // Open Add Account screen. id<GREYMatcher> add_account_matcher = @@ -480,7 +420,8 @@ // Re-open the sign-in screen. If it wasn't correctly dismissed previously, // this will fail. - OpenSignInFromSettings(); + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SignInMenuButton()]; id<GREYMatcher> signin_matcher = chrome_test_util::StaticTextWithAccessibilityLabelId( IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_DESCRIPTION); @@ -497,11 +438,6 @@ // that the authentication flow is correctly canceled and dismissed. // crbug.com/462202 - (void)testSignInCancelAuthenticationFlow { - // TODO(crbug.com/747444): Re-enable this test on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11."); - } - // Set up the fake identities. ios::FakeChromeIdentityService* identity_service = ios::FakeChromeIdentityService::GetInstanceFromChromeProvider(); @@ -514,10 +450,10 @@ // Syncing" dialog is shown during the second sign-in. This dialog will // effectively block the authentication flow, ensuring that the authentication // flow is always still running when the sign-in is being cancelled. - OpenSignInFromSettings(); - TapButtonWithAccessibilityLabel(identity2.userEmail); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_CONFIRMATION_OK_BUTTON); + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SignInMenuButton()]; + [ChromeEarlGreyUI signInToIdentityByEmail:identity2.userEmail]; + [ChromeEarlGreyUI confirmSigninConfirmationDialog]; AssertAuthenticatedIdentityInActiveProfile(identity2); // Go to Accounts Settings and tap the sign out button. @@ -532,11 +468,8 @@ TapButtonWithLabelId(IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE); AssertAuthenticatedIdentityInActiveProfile(nil); - // Start sign-in with |identity1|. - WaitForMatcher(grey_accessibilityID(kSettingsSignInCellId)); TapViewWithAccessibilityId(kSettingsSignInCellId); - TapButtonWithAccessibilityLabel(identity1.userEmail); - TapButtonWithLabelId(IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_SIGNIN_BUTTON); + [ChromeEarlGreyUI signInToIdentityByEmail:identity1.userEmail]; // Open new tab to cancel sign-in. OpenUrlCommand* command = @@ -545,7 +478,8 @@ // Re-open the sign-in screen. If it wasn't correctly dismissed previously, // this will fail. - OpenSignInFromSettings(); + [ChromeEarlGreyUI openSettingsMenu]; + [ChromeEarlGreyUI tapSettingsMenuButton:chrome_test_util::SignInMenuButton()]; id<GREYMatcher> signin_matcher = chrome_test_util::StaticTextWithAccessibilityLabelId( IDS_IOS_ACCOUNT_CONSISTENCY_SETUP_DESCRIPTION);
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn index dc43b12..2db0370 100644 --- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -96,15 +96,21 @@ "//base/test:test_support", "//components/keyed_service/ios", "//components/ntp_snippets", + "//components/reading_list/core", + "//ios/chrome/app/strings", "//ios/chrome/browser", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/ntp_snippets", + "//ios/chrome/browser/reading_list", + "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/content_suggestions/cells:cells_ui", "//ios/chrome/test/app:test_support", "//ios/chrome/test/earl_grey:test_support", "//ios/testing:ios_test_support", "//ios/testing/earl_grey:earl_grey_support", "//ios/third_party/earl_grey", + "//ios/web/public/test/http_server", + "//ui/strings", ] libs = [ "UIKit.framework",
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm index fd7cf891d..567c2a23 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm +++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm
@@ -79,6 +79,7 @@ cell.isAccessibilityElement = YES; cell.accessibilityLabel = [self accessibilityLabel]; cell.accessibilityCustomActions = [self customActions]; + cell.accessibilityIdentifier = self.title; } - (void)setImage:(UIImage*)image {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm index 9cdceb0cb..c89384b 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm
@@ -8,16 +8,27 @@ #include "base/test/scoped_command_line.h" #include "components/keyed_service/ios/browser_state_keyed_service_factory.h" #include "components/ntp_snippets/content_suggestions_service.h" +#include "components/reading_list/core/reading_list_entry.h" +#include "components/reading_list/core/reading_list_model.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/chrome_switches.h" #include "ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.h" #include "ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory_util.h" +#include "ios/chrome/browser/reading_list/reading_list_model_factory.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_learn_more_item.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h" +#include "ios/chrome/browser/ui/ui_util.h" +#include "ios/chrome/grit/ios_strings.h" #import "ios/chrome/test/app/chrome_test_util.h" +#import "ios/chrome/test/app/history_test_util.h" +#import "ios/chrome/test/app/tab_test_util.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" +#import "ios/chrome/test/earl_grey/chrome_matchers.h" #import "ios/chrome/test/earl_grey/chrome_test_case.h" +#import "ios/web/public/test/http_server/http_server.h" +#include "ios/web/public/test/http_server/http_server_util.h" +#include "ui/strings/grit/ui_strings.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -43,10 +54,16 @@ @interface ContentSuggestionsTestCase : ChromeTestCase { base::test::ScopedCommandLine _scopedCommandLine; } + +// Current non-incognito browser state. +@property(nonatomic, assign, readonly) ios::ChromeBrowserState* browserState; + @end @implementation ContentSuggestionsTestCase +#pragma mark - Setup/Teardown + + (void)setUp { [super setUp]; [self closeAllTabs]; @@ -69,6 +86,7 @@ [self closeAllTabs]; ios::ChromeBrowserState* browserState = chrome_test_util::GetOriginalBrowserState(); + ReadingListModelFactory::GetForBrowserState(browserState)->DeleteAllEntries(); // Resets the Service associated with this browserState to a service with // default providers. The previous service is deleted. @@ -78,11 +96,17 @@ [super tearDown]; } +#pragma mark - Tests + - (void)setUp { // The command line is set up before [super setUp] in order to have the NTP // opened with the command line already setup. base::CommandLine* commandLine = _scopedCommandLine.GetProcessCommandLine(); commandLine->AppendSwitch(switches::kEnableSuggestionsUI); + + ReadingListModel* readingListModel = + ReadingListModelFactory::GetForBrowserState(self.browserState); + readingListModel->DeleteAllEntries(); [super setUp]; } @@ -93,4 +117,91 @@ assertWithMatcher:grey_sufficientlyVisible()]; } +// Tests that when long pressing a Reading List entry, a context menu is shown. +- (void)testReadingListLongPress { + NSString* title = @"ReadingList test title"; + std::string sTitle = "ReadingList test title"; + ReadingListModel* readingListModel = + ReadingListModelFactory::GetForBrowserState(self.browserState); + readingListModel->AddEntry(GURL("http://chromium.org"), sTitle, + reading_list::ADDED_VIA_CURRENT_APP); + + [CellWithMatcher(grey_accessibilityID(title)) performAction:grey_longPress()]; + + [[EarlGrey + selectElementWithMatcher:chrome_test_util::ButtonWithAccessibilityLabelId( + IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB)] + assertWithMatcher:grey_interactable()]; + [[EarlGrey selectElementWithMatcher: + chrome_test_util::ButtonWithAccessibilityLabelId( + IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB)] + assertWithMatcher:grey_interactable()]; + [[EarlGrey + selectElementWithMatcher:chrome_test_util::ButtonWithAccessibilityLabelId( + IDS_IOS_CONTENT_SUGGESTIONS_REMOVE)] + assertWithMatcher:grey_interactable()]; + if (!IsIPadIdiom()) { + [[EarlGrey selectElementWithMatcher: + chrome_test_util::ButtonWithAccessibilityLabelId( + IDS_APP_CANCEL)] assertWithMatcher:grey_interactable()]; + } + + // No read later as it is already in the Reading List section. + [[EarlGrey + selectElementWithMatcher:chrome_test_util::ButtonWithAccessibilityLabelId( + IDS_IOS_CONTENT_CONTEXT_ADDTOREADINGLIST)] + assertWithMatcher:grey_nil()]; +} + +// Tests that when long pressing a Most Visited tile, a context menu is shown. +- (void)testMostVisitedLongPress { + std::map<GURL, std::string> responses; + GURL URL = web::test::HttpServer::MakeUrl("http://simple_tile.html"); + responses[URL] = + "<head><title>title1</title></head>" + "<body>You are here.</body>"; + web::test::SetUpSimpleHttpServer(responses); + + // Clear history and verify that the tile does not exist. + chrome_test_util::ClearBrowsingHistory(); + [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; + [ChromeEarlGrey loadURL:URL]; + + // After loading URL, need to do another action before opening a new tab + // with the icon present. + [ChromeEarlGrey goBack]; + + chrome_test_util::OpenNewTab(); + [[EarlGrey selectElementWithMatcher: + chrome_test_util::StaticTextWithAccessibilityLabel(@"title1")] + performAction:grey_longPress()]; + + [[EarlGrey + selectElementWithMatcher:chrome_test_util::ButtonWithAccessibilityLabelId( + IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB)] + assertWithMatcher:grey_interactable()]; + [[EarlGrey selectElementWithMatcher: + chrome_test_util::ButtonWithAccessibilityLabelId( + IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB)] + assertWithMatcher:grey_interactable()]; + [[EarlGrey + selectElementWithMatcher:chrome_test_util::ButtonWithAccessibilityLabelId( + IDS_IOS_CONTENT_SUGGESTIONS_REMOVE)] + assertWithMatcher:grey_interactable()]; + if (!IsIPadIdiom()) { + [[EarlGrey selectElementWithMatcher: + chrome_test_util::ButtonWithAccessibilityLabelId( + IDS_APP_CANCEL)] assertWithMatcher:grey_interactable()]; + } + + chrome_test_util::ClearBrowsingHistory(); + [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; +} + +#pragma mark - Properties + +- (ios::ChromeBrowserState*)browserState { + return chrome_test_util::GetOriginalBrowserState(); +} + @end
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index 87720b6..236111f4 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -294,10 +294,9 @@ layout:collectionViewLayout insetForSectionAtIndex:section]; if ([self.collectionUpdater isHeaderSection:section]) { - return parentInset; - } - if ([self.collectionUpdater isMostVisitedSection:section] || - [self.collectionUpdater isPromoSection:section]) { + parentInset.top = 0; + } else if ([self.collectionUpdater isMostVisitedSection:section] || + [self.collectionUpdater isPromoSection:section]) { CGFloat margin = content_suggestions::centeredTilesMarginForWidth( collectionView.frame.size.width); parentInset.left = margin;
diff --git a/ios/chrome/browser/ui/find_bar/BUILD.gn b/ios/chrome/browser/ui/find_bar/BUILD.gn index 9ca15b2..ad487457 100644 --- a/ios/chrome/browser/ui/find_bar/BUILD.gn +++ b/ios/chrome/browser/ui/find_bar/BUILD.gn
@@ -55,6 +55,7 @@ "//components/strings", "//ios/chrome/app/strings", "//ios/chrome/browser/find_in_page", + "//ios/chrome/browser/ui:ui", "//ios/chrome/browser/ui/tools_menu", "//ios/chrome/test/app:test_support", "//ios/chrome/test/earl_grey:test_support",
diff --git a/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm b/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm index 158fda6..36bb7af 100644 --- a/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm +++ b/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm
@@ -4,12 +4,14 @@ #import <XCTest/XCTest.h> +#include "base/ios/ios_util.h" #include "base/strings/string_number_conversions.h" #include "components/strings/grit/components_strings.h" #import "ios/chrome/browser/find_in_page/find_in_page_controller.h" #import "ios/chrome/browser/ui/find_bar/find_bar_controller_ios.h" #import "ios/chrome/browser/ui/find_bar/find_bar_view.h" #include "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h" +#include "ios/chrome/browser/ui/ui_util.h" #import "ios/chrome/test/app/tab_test_util.h" #import "ios/chrome/test/earl_grey/accessibility_util.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" @@ -94,6 +96,12 @@ // Tests that find in page allows iteration between search results and displays // correct number of results. - (void)testFindInPage { + // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once + // grey_typeText works on iOS 11. + if (base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); + } + // Type "find". [self typeFindInPageText:@"find"]; // Should be highlighting result 1 of 2.
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm b/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm index 816e6c52..5e9afa3 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm
@@ -144,11 +144,6 @@ EARL_GREY_TEST_DISABLED(@"Disabled for iPad due to device rotation bug."); } - // TODO(crbug.com/751803): Re-enable this test once the bug is fixed. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.") - } - NSString* ntpOmniboxLabel = l10n_util::GetNSString(IDS_OMNIBOX_EMPTY_HINT); NSString* focusedOmniboxLabel = l10n_util::GetNSString(IDS_ACCNAME_LOCATION); SelectNewTabPagePanel(NewTabPage::kHomePanel); @@ -220,11 +215,6 @@ // Tests focusing and defocusing the NTP's omnibox. - (void)testOmnibox { - // TODO(crbug.com/751803): Re-enable this test once the bug is fixed. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.") - } - // Empty the pasteboard: if it contains a link the Google Landing will not be // interactable. [UIPasteboard generalPasteboard].string = @""; @@ -293,11 +283,6 @@ EARL_GREY_TEST_SKIPPED(@"Skipped for iPad (no hidden toolbar in tablet)"); } - // TODO(crbug.com/751803): Re-enable this test once the bug is fixed. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11.") - } - NSString* toolsMenuLabel = l10n_util::GetNSString(IDS_IOS_TOOLBAR_SETTINGS); // Check that the toolbar's tab switcher and tools menu buttons are visible.
diff --git a/ios/chrome/browser/ui/payments/BUILD.gn b/ios/chrome/browser/ui/payments/BUILD.gn index a94fdc0f3..79f3852 100644 --- a/ios/chrome/browser/ui/payments/BUILD.gn +++ b/ios/chrome/browser/ui/payments/BUILD.gn
@@ -226,6 +226,8 @@ "payment_request_egtest_base.h", "payment_request_egtest_base.mm", "payment_request_misc_egtest.mm", + "payment_request_payment_method_identifier_egtest.mm", + "payment_request_payment_response_egtest.mm", ] deps = [ @@ -249,6 +251,7 @@ "//ios/web/public/test", "//ios/web/public/test/http_server", "//testing/gtest", + "//url", ] libs = [ "UIKit.framework",
diff --git a/ios/chrome/browser/ui/payments/payment_request_cancel_pay_abort_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_cancel_pay_abort_egtest.mm index caca4ece..9f6536e 100644 --- a/ios/chrome/browser/ui/payments/payment_request_cancel_pay_abort_egtest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_cancel_pay_abort_egtest.mm
@@ -4,11 +4,9 @@ #include <vector> -#include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/credit_card.h" -#include "components/autofill/core/browser/field_types.h" #include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h" #import "ios/chrome/browser/ui/payments/payment_request_egtest_base.h" @@ -204,29 +202,6 @@ [[EarlGrey selectElementWithMatcher:grey_accessibilityID( kPaymentRequestCollectionViewID)] assertWithMatcher:grey_nil()]; - - // Confirm that the appropriate response message was sent. Note that this does - // not test the structure of the response. - [self - waitForWebViewContainingTexts: - {base::UTF16ToUTF8(card.GetRawInfo(autofill::CREDIT_CARD_NUMBER)), - base::UTF16ToUTF8(card.GetRawInfo(autofill::CREDIT_CARD_NAME_FULL)), - base::UTF16ToUTF8(card.GetRawInfo(autofill::CREDIT_CARD_EXP_MONTH)), - base::UTF16ToUTF8( - card.GetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR)), - "111"}]; - [self - waitForWebViewContainingTexts: - {base::UTF16ToUTF8(profile.GetRawInfo(autofill::NAME_FIRST)), - base::UTF16ToUTF8(profile.GetRawInfo(autofill::NAME_LAST)), - base::UTF16ToUTF8(profile.GetRawInfo(autofill::ADDRESS_HOME_LINE1)), - base::UTF16ToUTF8(profile.GetRawInfo(autofill::ADDRESS_HOME_LINE2)), - base::UTF16ToUTF8( - profile.GetRawInfo(autofill::ADDRESS_HOME_COUNTRY)), - base::UTF16ToUTF8(profile.GetRawInfo(autofill::ADDRESS_HOME_ZIP)), - base::UTF16ToUTF8(profile.GetRawInfo(autofill::ADDRESS_HOME_CITY)), - base::UTF16ToUTF8( - profile.GetRawInfo(autofill::ADDRESS_HOME_STATE))}]; } // Tests that calling request.abort() successfully aborts the Payment Request.
diff --git a/ios/chrome/browser/ui/payments/payment_request_payment_method_identifier_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_payment_method_identifier_egtest.mm new file mode 100644 index 0000000..5a534b48 --- /dev/null +++ b/ios/chrome/browser/ui/payments/payment_request_payment_method_identifier_egtest.mm
@@ -0,0 +1,244 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <vector> + +#import "ios/chrome/browser/payments/payment_request_cache.h" +#import "ios/chrome/browser/ui/payments/payment_request_egtest_base.h" +#import "ios/chrome/test/app/chrome_test_util.h" +#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" +#import "ios/web/public/test/http_server/http_server.h" +#import "ios/web/public/test/web_view_interaction_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +using chrome_test_util::GetCurrentWebState; + +// URLs of the test pages. +const char kPaymentMethodIdentifierPage[] = + "https://components/test/data/payments/" + "payment_request_payment_method_identifier_test.html"; + +} // namepsace + +// Various tests to ensure that the payment method identifiers are correctly +// parsed. +@interface PaymentRequestPaymentMethodIdentifierEGTest + : PaymentRequestEGTestBase + +@end + +@implementation PaymentRequestPaymentMethodIdentifierEGTest + +#pragma mark - Tests + +// One network is specified in 'basic-card' data, one in supportedMethods. +- (void)testBasicCardNetworksSpecified { + [ChromeEarlGrey + loadURL:web::test::HttpServer::MakeUrl(kPaymentMethodIdentifierPage)]; + + [ChromeEarlGrey tapWebViewElementWithID:@"buy"]; + + const payments::PaymentRequestCache::PaymentRequestSet& requests = + [self paymentRequestsForWebState:GetCurrentWebState()]; + GREYAssertEqual(1U, requests.size(), @"Expected one request."); + std::vector<std::string> supportedCardNetworks = + (*requests.begin())->supported_card_networks(); + GREYAssertEqual(2U, supportedCardNetworks.size(), + @"Expected two supported card networks."); + // The networks appear in the order in which they were specified by the + // merchant. + GREYAssertEqual("mastercard", supportedCardNetworks[0], @""); + GREYAssertEqual("visa", supportedCardNetworks[1], @""); +} + +// Only specifying 'basic-card' with no supportedNetworks means all networks are +// supported. +- (void)testBasicCardNoNetworksSpecified { + [ChromeEarlGrey + loadURL:web::test::HttpServer::MakeUrl(kPaymentMethodIdentifierPage)]; + + [ChromeEarlGrey tapWebViewElementWithID:@"buyBasicCard"]; + + const payments::PaymentRequestCache::PaymentRequestSet& requests = + [self paymentRequestsForWebState:GetCurrentWebState()]; + GREYAssertEqual(1U, requests.size(), @"Expected one request."); + std::vector<std::string> supportedCardNetworks = + (*requests.begin())->supported_card_networks(); + GREYAssertEqual(8U, supportedCardNetworks.size(), + @"Expected eight supported card networks."); + // The default ordering is alphabetical. + GREYAssertEqual("amex", supportedCardNetworks[0], @""); + GREYAssertEqual("diners", supportedCardNetworks[1], @""); + GREYAssertEqual("discover", supportedCardNetworks[2], @""); + GREYAssertEqual("jcb", supportedCardNetworks[3], @""); + GREYAssertEqual("mastercard", supportedCardNetworks[4], @""); + GREYAssertEqual("mir", supportedCardNetworks[5], @""); + GREYAssertEqual("unionpay", supportedCardNetworks[6], @""); + GREYAssertEqual("visa", supportedCardNetworks[7], @""); +} + +// Specifying 'basic-card' after having explicitely included a network yields +// the expected order when in different supportedMethods lists. +- (void)testBasicCardNetworkThenBasicCardDifferentList { + [ChromeEarlGrey + loadURL:web::test::HttpServer::MakeUrl(kPaymentMethodIdentifierPage)]; + + web::test::ExecuteJavaScript(GetCurrentWebState(), + "buyHelper([{" + " supportedMethods: ['mastercard']," + "}, {" + " supportedMethods: ['basic-card']" + "}]);"); + + const payments::PaymentRequestCache::PaymentRequestSet& requests = + [self paymentRequestsForWebState:GetCurrentWebState()]; + GREYAssertEqual(1U, requests.size(), @"Expected one request."); + std::vector<std::string> supportedCardNetworks = + (*requests.begin())->supported_card_networks(); + GREYAssertEqual(8U, supportedCardNetworks.size(), + @"Expected eight supported card networks."); + // 'mastercard' is first because it was explicitely specified first. The rest + // is alphabetical. + GREYAssertEqual("mastercard", supportedCardNetworks[0], @""); + GREYAssertEqual("amex", supportedCardNetworks[1], @""); + GREYAssertEqual("diners", supportedCardNetworks[2], @""); + GREYAssertEqual("discover", supportedCardNetworks[3], @""); + GREYAssertEqual("jcb", supportedCardNetworks[4], @""); + GREYAssertEqual("mir", supportedCardNetworks[5], @""); + GREYAssertEqual("unionpay", supportedCardNetworks[6], @""); + GREYAssertEqual("visa", supportedCardNetworks[7], @""); +} + +// Specifying 'basic-card' after having explicitely included a network yields +// the expected order when in the same supportedMethods list. +- (void)testBasicCardNetworkThenBasicCardSameList { + [ChromeEarlGrey + loadURL:web::test::HttpServer::MakeUrl(kPaymentMethodIdentifierPage)]; + + web::test::ExecuteJavaScript(GetCurrentWebState(), + "buyHelper([{" + " supportedMethods: ['visa', 'basic-card']" + "}]);"); + + const payments::PaymentRequestCache::PaymentRequestSet& requests = + [self paymentRequestsForWebState:GetCurrentWebState()]; + GREYAssertEqual(1U, requests.size(), @"Expected one request."); + std::vector<std::string> supportedCardNetworks = + (*requests.begin())->supported_card_networks(); + GREYAssertEqual(8U, supportedCardNetworks.size(), + @"Expected eight supported card networks."); + // 'visa' is first because it was explicitely specified first. The rest + // is alphabetical. + GREYAssertEqual("visa", supportedCardNetworks[0], @""); + GREYAssertEqual("amex", supportedCardNetworks[1], @""); + GREYAssertEqual("diners", supportedCardNetworks[2], @""); + GREYAssertEqual("discover", supportedCardNetworks[3], @""); + GREYAssertEqual("jcb", supportedCardNetworks[4], @""); + GREYAssertEqual("mastercard", supportedCardNetworks[5], @""); + GREYAssertEqual("mir", supportedCardNetworks[6], @""); + GREYAssertEqual("unionpay", supportedCardNetworks[7], @""); +} + +// Specifying 'basic-card' with some networks after having explicitely included +// the same networks does not yield duplicates and has the expected order. +- (void)testBasicCardNetworkThenBasicCardWithSameNetwork { + [ChromeEarlGrey + loadURL:web::test::HttpServer::MakeUrl(kPaymentMethodIdentifierPage)]; + + web::test::ExecuteJavaScript( + GetCurrentWebState(), + "buyHelper([{" + " supportedMethods: ['mastercard', 'visa']" + "}, {" + " supportedMethods: ['basic-card']," + " data: {" + " supportedNetworks: ['visa', 'mastercard', 'jcb']," + " }" + "}]);"); + + const payments::PaymentRequestCache::PaymentRequestSet& requests = + [self paymentRequestsForWebState:GetCurrentWebState()]; + GREYAssertEqual(1U, requests.size(), @"Expected one request."); + std::vector<std::string> supportedCardNetworks = + (*requests.begin())->supported_card_networks(); + GREYAssertEqual(3U, supportedCardNetworks.size(), + @"Expected three supported card networks."); + GREYAssertEqual("mastercard", supportedCardNetworks[0], @""); + GREYAssertEqual("visa", supportedCardNetworks[1], @""); + GREYAssertEqual("jcb", supportedCardNetworks[2], @""); +} + +// A url-based payment method identifier is only supported if it has an https +// scheme. +- (void)testURLBasedPaymentMethodIdentifierWithInvalidScheme { + [ChromeEarlGrey + loadURL:web::test::HttpServer::MakeUrl(kPaymentMethodIdentifierPage)]; + + web::test::ExecuteJavaScript( + GetCurrentWebState(), + "buyHelper([{" + " supportedMethods: ['https://bobpay.xyz', 'http://bobpay.xyz']" + "}, {" + " supportedMethods: ['basic-card']" + "}]);"); + + const payments::PaymentRequestCache::PaymentRequestSet& requests = + [self paymentRequestsForWebState:GetCurrentWebState()]; + GREYAssertEqual(1U, requests.size(), @"Expected one request."); + const std::vector<GURL>& urlPaymentMethodIdentifiers = + (*requests.begin())->url_payment_method_identifiers(); + GREYAssertEqual(1U, urlPaymentMethodIdentifiers.size(), + @"Expected one URL-based payment method identifier."); + GREYAssertEqual(GURL("https://bobpay.xyz"), urlPaymentMethodIdentifiers[0], + @""); +} + +// A url-based payment method identifier is only supported if it has an https +// scheme. +- (void)testMultiplePaymentMethodIdentifiers { + [ChromeEarlGrey + loadURL:web::test::HttpServer::MakeUrl(kPaymentMethodIdentifierPage)]; + + web::test::ExecuteJavaScript( + GetCurrentWebState(), + "buyHelper([{" + " supportedMethods: ['https://bobpay.xyz', 'http://bobpay.xyz']" + "}, {" + " supportedMethods: ['mastercard', 'visa', 'https://alicepay.com']" + "}, {" + " supportedMethods: ['basic-card']," + " data: {" + " supportedNetworks: ['visa', 'mastercard', 'jcb']," + " }" + "}]);"); + + const payments::PaymentRequestCache::PaymentRequestSet& requests = + [self paymentRequestsForWebState:GetCurrentWebState()]; + GREYAssertEqual(1U, requests.size(), @"Expected one request."); + + std::vector<std::string> supportedCardNetworks = + (*requests.begin())->supported_card_networks(); + GREYAssertEqual(3U, supportedCardNetworks.size(), + @"Expected three supported card networks."); + GREYAssertEqual("mastercard", supportedCardNetworks[0], @""); + GREYAssertEqual("visa", supportedCardNetworks[1], @""); + GREYAssertEqual("jcb", supportedCardNetworks[2], @""); + + const std::vector<GURL>& urlPaymentMethodIdentifiers = + (*requests.begin())->url_payment_method_identifiers(); + GREYAssertEqual(2U, urlPaymentMethodIdentifiers.size(), + @"Expected two URL-based payment method identifier."); + GREYAssertEqual(GURL("https://bobpay.xyz"), urlPaymentMethodIdentifiers[0], + @""); + GREYAssertEqual(GURL("https://alicepay.com"), urlPaymentMethodIdentifiers[1], + @""); +} + +@end
diff --git a/ios/chrome/browser/ui/payments/payment_request_payment_response_egtest.mm b/ios/chrome/browser/ui/payments/payment_request_payment_response_egtest.mm new file mode 100644 index 0000000..9a52701 --- /dev/null +++ b/ios/chrome/browser/ui/payments/payment_request_payment_response_egtest.mm
@@ -0,0 +1,248 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <vector> + +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/credit_card.h" +#include "components/autofill/core/browser/field_types.h" +#include "components/strings/grit/components_strings.h" +#import "ios/chrome/browser/payments/payment_request_cache.h" +#include "ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h" +#import "ios/chrome/browser/ui/payments/payment_request_egtest_base.h" +#import "ios/chrome/browser/ui/payments/payment_request_error_view_controller.h" +#import "ios/chrome/browser/ui/payments/payment_request_view_controller.h" +#import "ios/chrome/test/app/chrome_test_util.h" +#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" +#import "ios/chrome/test/earl_grey/chrome_matchers.h" +#import "ios/web/public/test/http_server/http_server.h" +#import "ios/web/public/test/web_view_interaction_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +using chrome_test_util::ButtonWithAccessibilityLabelId; +using chrome_test_util::GetCurrentWebState; + +// URLs of the test pages. +const char kNoShippingPage[] = + "https://components/test/data/payments/" + "payment_request_no_shipping_test.html"; +const char kFreeShippingPage[] = + "https://components/test/data/payments/" + "payment_request_free_shipping_test.html"; +const char kContactDetailsPage[] = + "https://components/test/data/payments/" + "payment_request_contact_details_and_free_shipping_test.html"; +const char kRequestEmailPage[] = + "https://components/test/data/payments/" + "payment_request_email_and_free_shipping_test.html"; + +} // namepsace + +// Various tests for the validity of the payment response generated with an +// autofill payment instrument. +@interface PaymentRequestPaymentResponseAutofillPaymentInstrumentEGTest + : PaymentRequestEGTestBase + +@end + +@implementation PaymentRequestPaymentResponseAutofillPaymentInstrumentEGTest + +#pragma mark - Tests + +// Tests that the PaymentResponse contains all the required fields for an +// Autofill payment instrument. +- (void)testPaymentResponseNoShipping { + // Create a billing address and a card that uses it. + autofill::AutofillProfile billingAddress = autofill::test::GetFullProfile(); + [self addAutofillProfile:billingAddress]; + autofill::CreditCard card = autofill::test::GetCreditCard(); // visa + card.set_billing_address_id(billingAddress.guid()); + [self addCreditCard:card]; + + [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kNoShippingPage)]; + + [ChromeEarlGrey tapWebViewElementWithID:@"buy"]; + + // Tap the buy button. + [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( + IDS_PAYMENTS_PAY_BUTTON)] + performAction:grey_tap()]; + + // Type in the CVC. + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"CVC_textField")] + performAction:grey_typeText(@"123")]; + + // Tap the confirm button. + [[EarlGrey + selectElementWithMatcher:ButtonWithAccessibilityLabelId(IDS_ACCNAME_OK)] + performAction:grey_tap()]; + + // Test that the card details were sent to the merchant. + [self waitForWebViewContainingTexts:{"\"methodName\": \"visa\"", + "\"details\": {", + "\"cardNumber\": \"4111111111111111\"", + "\"cardSecurityCode\": \"123\"", + "\"cardholderName\": \"Test User\"", + "\"expiryMonth\": \"11\"", + "\"expiryYear\": \"2022\""}]; + + // Test that the billing address was sent to the merchant. + [self + waitForWebViewContainingTexts:{"\"billingAddress\": {", + "\"addressLine\": [", "\"666 Erebus St.\"", + "\"Apt 8\"", "\"city\": \"Elysium\"", + "\"country\": \"US\"", + "\"dependentLocality\": \"\"", + "\"languageCode\": \"\"", + "\"organization\": \"Underworld\"", + "\"phone\": \"+16502111111\"", + "\"postalCode\": \"91111\"", + "\"recipient\": \"John H. Doe\"", + "\"region\": \"CA\"", + "\"sortingCode\": \"\""}]; + + // Test that the no shipping address, shipping option, or contact details was + // sent to the merchant. + [self waitForWebViewContainingTexts:{"\"shippingAddress\": null", + "\"shippingOption\": null", + "\"payerName\": null", + "\"payerEmail\": null", + "\"payerPhone\": null"}]; +} + +// Tests that the PaymentResponse contains all the required fields for a +// shipping address and shipping option. +- (void)testPaymentResponseFreeShipping { + // Create a billing address and a card that uses it. + autofill::AutofillProfile billingAddress = autofill::test::GetFullProfile(); + [self addAutofillProfile:billingAddress]; + autofill::CreditCard card = autofill::test::GetCreditCard(); // visa + card.set_billing_address_id(billingAddress.guid()); + [self addCreditCard:card]; + + // Create a shipping address with a higher frecency score, so that it is + // selected as the default shipping address. + autofill::AutofillProfile shippingAddress = autofill::test::GetFullProfile2(); + shippingAddress.set_use_count(2000); + [self addAutofillProfile:shippingAddress]; + + [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kFreeShippingPage)]; + + [ChromeEarlGrey tapWebViewElementWithID:@"buy"]; + + // Tap the buy button. + [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( + IDS_PAYMENTS_PAY_BUTTON)] + performAction:grey_tap()]; + + // Type in the CVC. + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"CVC_textField")] + performAction:grey_typeText(@"123")]; + + // Tap the confirm button. + [[EarlGrey + selectElementWithMatcher:ButtonWithAccessibilityLabelId(IDS_ACCNAME_OK)] + performAction:grey_tap()]; + + // Test that the billing address was sent to the merchant. + [self waitForWebViewContainingTexts:{"\"shippingAddress\": {", + "\"addressLine\": [", + "\"123 Main Street\"", "\"Unit 1\"", + "\"city\": \"Greensdale\"", + "\"country\": \"US\"", + "\"dependentLocality\": \"\"", + "\"languageCode\": \"\"", + "\"organization\": \"ACME\"", + "\"phone\": \"+13105557889\"", + "\"postalCode\": \"48838\"", + "\"recipient\": \"Jane A. Smith\"", + "\"region\": \"MI\"", + "\"sortingCode\": \"\""}]; + + // Test that the shipping option was sent to the merchant. + [self waitForWebViewContainingTexts: + {"\"shippingOption\": \"freeShippingOption\""}]; + + // Test that the no contact details was sent to the merchant. + [self waitForWebViewContainingTexts:{"\"payerName\": null", + "\"payerEmail\": null", + "\"payerPhone\": null"}]; +} + +// Tests that the PaymentResponse contains all the required fields for contact +// details when all three details are requested. +- (void)testPaymentResponseAllContactDetails { + // Create a billing address and a card that uses it. + autofill::AutofillProfile billingAddress = autofill::test::GetFullProfile(); + [self addAutofillProfile:billingAddress]; + autofill::CreditCard card = autofill::test::GetCreditCard(); // visa + card.set_billing_address_id(billingAddress.guid()); + [self addCreditCard:card]; + + [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kContactDetailsPage)]; + + [ChromeEarlGrey tapWebViewElementWithID:@"buy"]; + + // Tap the buy button. + [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( + IDS_PAYMENTS_PAY_BUTTON)] + performAction:grey_tap()]; + + // Type in the CVC. + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"CVC_textField")] + performAction:grey_typeText(@"123")]; + + // Tap the confirm button. + [[EarlGrey + selectElementWithMatcher:ButtonWithAccessibilityLabelId(IDS_ACCNAME_OK)] + performAction:grey_tap()]; + + // Test that the contact details were sent to the merchant. + [self waitForWebViewContainingTexts:{"\"payerName\": \"John H. Doe\"", + "\"payerEmail\": \"johndoe@hades.com\"", + "\"payerPhone\": \"+16502111111\""}]; +} + +// Tests that the PaymentResponse contains all the required fields for contact +// details when only one detail is requested. +- (void)testPaymentResponseOneContactDetail { + // Create a billing address and a card that uses it. + autofill::AutofillProfile billingAddress = autofill::test::GetFullProfile(); + [self addAutofillProfile:billingAddress]; + autofill::CreditCard card = autofill::test::GetCreditCard(); // visa + card.set_billing_address_id(billingAddress.guid()); + [self addCreditCard:card]; + + [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kRequestEmailPage)]; + + [ChromeEarlGrey tapWebViewElementWithID:@"buy"]; + + // Tap the buy button. + [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabelId( + IDS_PAYMENTS_PAY_BUTTON)] + performAction:grey_tap()]; + + // Type in the CVC. + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"CVC_textField")] + performAction:grey_typeText(@"123")]; + + // Tap the confirm button. + [[EarlGrey + selectElementWithMatcher:ButtonWithAccessibilityLabelId(IDS_ACCNAME_OK)] + performAction:grey_tap()]; + + // Test that the contact details were sent to the merchant. + [self waitForWebViewContainingTexts:{"\"payerName\": null", + "\"payerEmail\": \"johndoe@hades.com\"", + "\"payerPhone\": null"}]; +} + +@end
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn index 24eba41..bee6b5d 100644 --- a/ios/chrome/test/earl_grey/BUILD.gn +++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -55,7 +55,6 @@ chrome_ios_eg_test("ios_chrome_ui_egtests") { deps = [ "//ios/chrome/app/safe_mode:eg_tests", - "//ios/chrome/browser/content_suggestions:eg_tests", "//ios/chrome/browser/ui:eg_tests", "//ios/chrome/browser/ui/activity_services:eg_tests", "//ios/chrome/browser/ui/alert_coordinator:eg_tests", @@ -183,6 +182,7 @@ "//components/strings", "//ios/chrome/app/strings", "//ios/chrome/browser/ui", + "//ios/chrome/browser/ui/authentication:authentication", "//ios/chrome/browser/ui/collection_view/cells", "//ios/chrome/browser/ui/commands:commands", "//ios/chrome/browser/ui/omnibox:omnibox_internal",
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h index 3377f13..cdfb2c8 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h
@@ -62,6 +62,14 @@ // GREYAssert is induced. + (void)waitForToolbarVisible:(BOOL)isVisible; +// Signs in the identity for the specific |userEmail|. This must be called from +// the NTP, and it doesn't dismiss the sign in confirmation page. ++ (void)signInToIdentityByEmail:(NSString*)userEmail; + +// Confirms the sign in confirmation page, scrolls first to make the OK button +// visible on short devices (e.g. iPhone 5s). ++ (void)confirmSigninConfirmationDialog; + @end #endif // IOS_CHROME_TEST_EARL_GREY_CHROME_EARL_GREY_UI_H_
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm index 97639d80..e344cd60 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm
@@ -4,12 +4,15 @@ #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" +#include "components/strings/grit/components_strings.h" +#include "ios/chrome/browser/ui/authentication/signin_confirmation_view_controller.h" #import "ios/chrome/browser/ui/settings/accounts_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/privacy_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_collection_view_controller.h" #import "ios/chrome/browser/ui/tools_menu/tools_menu_constants.h" #import "ios/chrome/browser/ui/tools_menu/tools_popup_controller.h" #import "ios/chrome/browser/ui/uikit_ui_util.h" +#include "ios/chrome/grit/ios_strings.h" #import "ios/chrome/test/app/chrome_test_util.h" #include "ios/chrome/test/app/navigation_test_util.h" #import "ios/chrome/test/earl_grey/chrome_matchers.h" @@ -21,6 +24,8 @@ #error "This file requires ARC support." #endif +using chrome_test_util::AccountConsistencyConfirmationOkButton; +using chrome_test_util::AccountConsistencySetupSigninButton; using chrome_test_util::ButtonWithAccessibilityLabel; using chrome_test_util::ClearBrowsingDataCollectionView; using chrome_test_util::SettingsMenuButton; @@ -160,4 +165,29 @@ errorMessage); } ++ (void)signInToIdentityByEmail:(NSString*)userEmail { + // Sign in to |userEmail|. + [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(userEmail)] + performAction:grey_tap()]; + [[EarlGrey selectElementWithMatcher:AccountConsistencySetupSigninButton()] + performAction:grey_tap()]; +} + ++ (void)confirmSigninConfirmationDialog { + // Confirm sign in. "More" button is shown on short devices (e.g. iPhone 5s, + // iPhone SE), so needs to scroll first to dismiss the "More" button before + // taping on "OK". + // Cannot directly scroll on |kSignInConfirmationCollectionViewId| because it + // is a MDC collection view, not a UICollectionView, so itself is not + // scrollable. + id<GREYMatcher> signinUICollectionViewMatcher = grey_allOf( + grey_ancestor(grey_accessibilityID(kSigninConfirmationCollectionViewId)), + grey_kindOfClass([UICollectionView class]), nil); + [[EarlGrey selectElementWithMatcher:signinUICollectionViewMatcher] + performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)]; + + [[EarlGrey selectElementWithMatcher:AccountConsistencyConfirmationOkButton()] + performAction:grey_tap()]; +} + @end
diff --git a/ios/web/payments/payment_request.cc b/ios/web/payments/payment_request.cc index 51f9f80..c535f9d7 100644 --- a/ios/web/payments/payment_request.cc +++ b/ios/web/payments/payment_request.cc
@@ -5,6 +5,7 @@ #include "ios/web/public/payments/payment_request.h" #include "base/json/json_reader.h" +#include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" @@ -398,14 +399,15 @@ } PaymentResponse::PaymentResponse() {} -PaymentResponse::PaymentResponse(const PaymentResponse& other) = default; PaymentResponse::~PaymentResponse() = default; bool PaymentResponse::operator==(const PaymentResponse& other) const { return this->payment_request_id == other.payment_request_id && this->method_name == other.method_name && this->details == other.details && - this->shipping_address == other.shipping_address && + ((!this->shipping_address && !other.shipping_address) || + (this->shipping_address && other.shipping_address && + *this->shipping_address == *other.shipping_address)) && this->shipping_option == other.shipping_option && this->payer_name == other.payer_name && this->payer_email == other.payer_email && @@ -423,25 +425,20 @@ result->SetString(kPaymentResponseId, this->payment_request_id); result->SetString(kPaymentResponseMethodName, this->method_name); // |this.details| is a json-serialized string. Parse it to a base::Value so - // that when |this| is converted to a JSON string, |this.details| won't get - // json-escaped. + // that when |result| is converted to a JSON string, the "details" property + // won't get json-escaped. std::unique_ptr<base::Value> details = base::JSONReader().ReadToValue(this->details); - if (details) - result->Set(kPaymentResponseDetails, std::move(details)); - if (!this->shipping_address.ToDictionaryValue()->empty()) { - result->Set(kPaymentResponseShippingAddress, - this->shipping_address.ToDictionaryValue()); - } - if (!this->shipping_option.empty()) - result->SetString(kPaymentResponseShippingOption, this->shipping_option); - if (!this->payer_name.empty()) - result->SetString(kPaymentResponsePayerName, this->payer_name); - if (!this->payer_email.empty()) - result->SetString(kPaymentResponsePayerEmail, this->payer_email); - if (!this->payer_phone.empty()) - result->SetString(kPaymentResponsePayerPhone, this->payer_phone); - + result->Set(kPaymentResponseDetails, + details ? std::move(details) : base::MakeUnique<base::Value>()); + result->Set(kPaymentResponseShippingAddress, + this->shipping_address + ? this->shipping_address->ToDictionaryValue() + : base::MakeUnique<base::Value>()); + result->SetString(kPaymentResponseShippingOption, this->shipping_option); + result->SetString(kPaymentResponsePayerName, this->payer_name); + result->SetString(kPaymentResponsePayerEmail, this->payer_email); + result->SetString(kPaymentResponsePayerPhone, this->payer_phone); return result; }
diff --git a/ios/web/payments/payment_request_unittest.cc b/ios/web/payments/payment_request_unittest.cc index 61e5b9e..515942c 100644 --- a/ios/web/payments/payment_request_unittest.cc +++ b/ios/web/payments/payment_request_unittest.cc
@@ -452,20 +452,12 @@ expected_value.SetString("requestId", ""); expected_value.SetString("methodName", ""); - std::unique_ptr<base::DictionaryValue> shipping_address( - new base::DictionaryValue); - shipping_address->SetString("country", ""); - shipping_address->Set("addressLine", base::MakeUnique<base::ListValue>()); - shipping_address->SetString("region", ""); - shipping_address->SetString("dependentLocality", ""); - shipping_address->SetString("city", ""); - shipping_address->SetString("postalCode", ""); - shipping_address->SetString("languageCode", ""); - shipping_address->SetString("sortingCode", ""); - shipping_address->SetString("organization", ""); - shipping_address->SetString("recipient", ""); - shipping_address->SetString("phone", ""); - expected_value.Set("shippingAddress", std::move(shipping_address)); + expected_value.Set("details", base::MakeUnique<base::Value>()); + expected_value.Set("shippingAddress", base::MakeUnique<base::Value>()); + expected_value.SetString("shippingOption", ""); + expected_value.SetString("payerName", ""); + expected_value.SetString("payerEmail", ""); + expected_value.SetString("payerPhone", ""); PaymentResponse payment_response; EXPECT_TRUE( @@ -539,7 +531,9 @@ &payment_response_stringified_details); payment_response.details = payment_response_stringified_details; - payment_response.shipping_address.postal_code = base::ASCIIToUTF16("94115"); + payment_response.shipping_address = + base::MakeUnique<payments::PaymentAddress>(); + payment_response.shipping_address->postal_code = base::ASCIIToUTF16("94115"); payment_response.shipping_option = base::ASCIIToUTF16("666"); payment_response.payer_name = base::ASCIIToUTF16("Jane Doe"); payment_response.payer_email = base::ASCIIToUTF16("jane@example.com"); @@ -889,4 +883,4 @@ EXPECT_EQ(response1, response2); } -} // namespace web \ No newline at end of file +} // namespace web
diff --git a/ios/web/public/payments/payment_request.h b/ios/web/public/payments/payment_request.h index ad52bd08..62c3ab6 100644 --- a/ios/web/public/payments/payment_request.h +++ b/ios/web/public/payments/payment_request.h
@@ -264,7 +264,6 @@ class PaymentResponse { public: PaymentResponse(); - PaymentResponse(const PaymentResponse& other); ~PaymentResponse(); bool operator==(const PaymentResponse& other) const; @@ -287,7 +286,7 @@ // If request_shipping was set to true in the PaymentOptions passed to the // PaymentRequest constructor, this will be the full and final shipping // address chosen by the user. - payments::PaymentAddress shipping_address; + std::unique_ptr<payments::PaymentAddress> shipping_address; // If the request_shipping flag was set to true in the PaymentOptions passed // to the PaymentRequest constructor, this will be the id attribute of the
diff --git a/media/BUILD.gn b/media/BUILD.gn index fc92bb2..8134d97 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -27,6 +27,7 @@ "ENABLE_MSE_MPEG2TS_STREAM_PARSER=$enable_mse_mpeg2ts_stream_parser", "ENABLE_RUNTIME_MEDIA_RENDERER_SELECTION=$enable_runtime_media_renderer_selection", "ENABLE_MEDIA_REMOTING=$enable_media_remoting", + "ENABLE_MEDIA_REMOTING_RPC=$enable_media_remoting_rpc", "ENABLE_WEBRTC=$enable_webrtc", "USE_PROPRIETARY_CODECS=$proprietary_codecs", ]
diff --git a/media/capture/video/fake_video_capture_device_factory.cc b/media/capture/video/fake_video_capture_device_factory.cc index 6043c89..f668a61cf 100644 --- a/media/capture/video/fake_video_capture_device_factory.cc +++ b/media/capture/video/fake_video_capture_device_factory.cc
@@ -12,6 +12,7 @@ #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "build/build_config.h" #include "media/base/media_switches.h" namespace { @@ -207,6 +208,8 @@ VideoCaptureApi::WIN_DIRECT_SHOW #elif defined(OS_ANDROID) VideoCaptureApi::ANDROID_API2_LEGACY +#elif defined(OS_FUCHSIA) + VideoCaptureApi::UNKNOWN #endif ); entry_index++;
diff --git a/media/filters/decoder_stream.cc b/media/filters/decoder_stream.cc index ab12038..83f1176 100644 --- a/media/filters/decoder_stream.cc +++ b/media/filters/decoder_stream.cc
@@ -754,6 +754,14 @@ return; } + // Re-enable fallback to software after reinitialization. This is the last + // place we can clear that state, and as such is the least likely to interfere + // with the rest of the fallback algorithm. + // TODO(tguilbert): investigate setting this flag at an earlier time. This + // could fix the hypothetical edge case of receiving a decode error when + // flushing the decoder during a seek operation. + decoder_produced_a_frame_ = false; + ReadFromDemuxerStream(); }
diff --git a/media/filters/video_frame_stream_unittest.cc b/media/filters/video_frame_stream_unittest.cc index b53d42d..c642664a 100644 --- a/media/filters/video_frame_stream_unittest.cc +++ b/media/filters/video_frame_stream_unittest.cc
@@ -942,6 +942,52 @@ ASSERT_EQ(VideoFrameStream::DECODE_ERROR, last_read_status_); } +// This tests verifies that we properly fallback to a new decoder if the first +// decode after a config change fails. +TEST_P(VideoFrameStreamTest, + FallbackDecoder_SelectedOnMidstreamDecodeErrorAfterReinitialization) { + // For simplicity of testing, this test applies only when there is no decoder + // delay and parallel decoding is disabled. + if (GetParam().decoding_delay != 0 || GetParam().parallel_decoding > 1) + return; + + Initialize(); + + // Note: Completes decoding one frame, results in Decode() being called with + // second frame that is not completed. + ReadOneFrame(); + + // Verify that the first frame was decoded successfully. + EXPECT_FALSE(pending_read_); + EXPECT_GT(decoder_->total_bytes_decoded(), 0); + EXPECT_EQ(VideoFrameStream::OK, last_read_status_); + + // Continue up to the point of reinitialization. + EnterPendingState(DEMUXER_READ_CONFIG_CHANGE); + + // Hold decodes to prevent a frame from being outputed upon reinitialization. + decoder_->HoldDecode(); + SatisfyPendingCallback(DEMUXER_READ_CONFIG_CHANGE); + + // DecoderStream sends an EOS to flush the decoder during config changes. + // Let the EOS decode be satisfied to properly complete the decoder reinit. + decoder_->SatisfySingleDecode(); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(pending_read_); + + // Fail the first decode, before a frame can be outputed. + decoder_->SimulateError(); + base::RunLoop().RunUntilIdle(); + + ReadOneFrame(); + + // Verify that fallback happened. + EXPECT_EQ(GetDecoderName(1), decoder_->GetDisplayName()); + EXPECT_FALSE(pending_read_); + EXPECT_EQ(VideoFrameStream::OK, last_read_status_); + EXPECT_GT(decoder_->total_bytes_decoded(), 0); +} + TEST_P(VideoFrameStreamTest, FallbackDecoder_DecodeErrorTwice_AfterReinitialization) { Initialize();
diff --git a/media/gpu/avda_codec_allocator.cc b/media/gpu/avda_codec_allocator.cc index b549774..be84754d 100644 --- a/media/gpu/avda_codec_allocator.cc +++ b/media/gpu/avda_codec_allocator.cc
@@ -229,8 +229,31 @@ // |client| has been destroyed. Free |media_codec| on the right thread. // Note that this also preserves |surface_bundle| until |media_codec| has // been released, in case our ref to it is the last one. - if (media_codec) - ReleaseMediaCodec(std::move(media_codec), surface_bundle); + if (!media_codec) + return; + + // If there are no registered clients, then the threads are stopped or are + // stopping. We must restart them / cancel any pending stop requests before + // we can post codec destruction to them. In the "restart them" case, the + // threads aren't running. In the "cancel...requests" case, the threads are + // running, but we're trying to clear them out via a DoNothing task posted + // there. Once that completes, there will be a join on the main thread. If + // we post, then it will be ordered after the DoNothing, but before the join + // on the main thread (this thread). If the destruction task hangs, then so + // will the join. + // + // We register a fake client to make sure that the threads are ready. + // + // If we can't start the thread, then, well, good luck. + if (!StartThread(nullptr)) + return; + + ReleaseMediaCodec(std::move(media_codec), surface_bundle); + + // We can stop the threads immediately. If other clients are around, then + // this will do nothing. Otherwise, this will order the join after the + // release completes successfully. + StopThread(nullptr); return; }
diff --git a/media/media_options.gni b/media/media_options.gni index 0839441..26217a65 100644 --- a/media/media_options.gni +++ b/media/media_options.gni
@@ -59,7 +59,7 @@ # which are encoded using HEVC require |enable_hevc_demuxing| to be enabled. enable_dolby_vision_demuxing = proprietary_codecs && is_chromecast - enable_webrtc = !is_cast_audio_only + enable_webrtc = !is_cast_audio_only && !is_fuchsia # Enable HLS with SAMPLE-AES decryption. # Enabled by default on the cast desktop implementation to allow unit tests of @@ -204,3 +204,9 @@ # devices when the tab is being casted and other conditions are met. enable_media_remoting = !is_chromecast && !is_ios } + +declare_args() { + # Media Remoting RPC is disabled on Android since it's unused but increases + # the native binary size by ~70Kb. + enable_media_remoting_rpc = enable_media_remoting && !is_android +}
diff --git a/media/remoting/BUILD.gn b/media/remoting/BUILD.gn index f1ed703e..99ba2a0 100644 --- a/media/remoting/BUILD.gn +++ b/media/remoting/BUILD.gn
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//media/media_options.gni") import("//testing/test.gni") import("//third_party/protobuf/proto_library.gni") @@ -36,12 +37,8 @@ source_set("remoting") { sources = [ - "courier_renderer.cc", - "courier_renderer.h", "courier_renderer_factory.cc", "courier_renderer_factory.h", - "demuxer_stream_adapter.cc", - "demuxer_stream_adapter.h", "metrics.cc", "metrics.h", "remoting_cdm.cc", @@ -58,55 +55,73 @@ "shared_session.h", "sink_availability_observer.cc", "sink_availability_observer.h", - "triggers.h", ] deps = [ - ":rpc", "//base", "//media", "//media/mojo/interfaces:remoting", "//mojo/public/cpp/bindings", "//ui/gfx", ] + + if (enable_media_remoting_rpc) { + sources += [ + "courier_renderer.cc", + "courier_renderer.h", + "demuxer_stream_adapter.cc", + "demuxer_stream_adapter.h", + "triggers.h", + ] + + deps += [ ":rpc" ] + } } source_set("media_remoting_tests") { testonly = true sources = [ - "courier_renderer_unittest.cc", - "demuxer_stream_adapter_unittest.cc", - "end2end_test_renderer.cc", - "end2end_test_renderer.h", - "fake_media_resource.cc", - "fake_media_resource.h", "fake_remoter.cc", "fake_remoter.h", - "integration_test.cc", - "proto_utils_unittest.cc", - "receiver.cc", - "receiver.h", "renderer_controller_unittest.cc", - "rpc_broker_unittest.cc", - "stream_provider.cc", - "stream_provider.h", ] deps = [ ":remoting", - ":rpc", "//base", "//base/test:test_support", "//media", "//media/base:test_support", "//media/mojo/interfaces:remoting", - "//media/test:pipeline_integration_test_base", "//testing/gmock", "//testing/gtest", - "//ui/gfx:test_support", - "//ui/gfx/geometry", "//url", ] + + if (!is_android) { + sources += [ + "courier_renderer_unittest.cc", + "demuxer_stream_adapter_unittest.cc", + "end2end_test_renderer.cc", + "end2end_test_renderer.h", + "fake_media_resource.cc", + "fake_media_resource.h", + "integration_test.cc", + "proto_utils_unittest.cc", + "receiver.cc", + "receiver.h", + "rpc_broker_unittest.cc", + "stream_provider.cc", + "stream_provider.h", + ] + + deps += [ + ":rpc", + "//media/test:pipeline_integration_test_base", + "//ui/gfx:test_support", + "//ui/gfx/geometry", + ] + } } test("media_remoting_unittests") {
diff --git a/media/remoting/courier_renderer_factory.cc b/media/remoting/courier_renderer_factory.cc index b1e4290..27453a1 100644 --- a/media/remoting/courier_renderer_factory.cc +++ b/media/remoting/courier_renderer_factory.cc
@@ -6,8 +6,13 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "build/buildflag.h" #include "media/base/overlay_info.h" -#include "media/remoting/courier_renderer.h" +#include "media/media_features.h" + +#if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC) +#include "media/remoting/courier_renderer.h" // nogncheck +#endif namespace media { namespace remoting { @@ -25,8 +30,12 @@ VideoRendererSink* video_renderer_sink, const RequestOverlayInfoCB& request_overlay_info_cb) { DCHECK(IsRemotingActive()); +#if !defined(ENABLE_MEDIA_REMOTING_RPC) + return nullptr; +#else return base::MakeUnique<CourierRenderer>( media_task_runner, controller_->GetWeakPtr(), video_renderer_sink); +#endif } bool CourierRendererFactory::IsRemotingActive() {
diff --git a/media/remoting/fake_remoter.cc b/media/remoting/fake_remoter.cc index f032542..205a4b7 100644 --- a/media/remoting/fake_remoter.cc +++ b/media/remoting/fake_remoter.cc
@@ -9,11 +9,16 @@ #include "base/callback.h" #include "base/memory/ptr_util.h" #include "base/threading/thread_task_runner_handle.h" -#include "media/remoting/proto_utils.h" +#include "build/buildflag.h" +#include "media/media_features.h" #include "media/remoting/shared_session.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "testing/gtest/include/gtest/gtest.h" +#if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC) +#include "media/remoting/proto_utils.h" // nogncheck +#endif + namespace media { namespace remoting { @@ -45,6 +50,9 @@ return false; } +#if !BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC) + return true; +#else const std::vector<uint8_t>& data = received_frame_list[index]; scoped_refptr<DecoderBuffer> media_buffer = ByteArrayToDecoderBuffer(data.data(), data.size()); @@ -83,6 +91,7 @@ } } return return_value; +#endif // !defined(ENABLE_MEDIA_REMOTING_RPC) } void FakeRemotingDataStreamSender::ConsumeDataChunk(
diff --git a/media/remoting/renderer_controller.cc b/media/remoting/renderer_controller.cc index 1967579..94381f0 100644 --- a/media/remoting/renderer_controller.cc +++ b/media/remoting/renderer_controller.cc
@@ -11,6 +11,8 @@ #include "base/time/tick_clock.h" #include "base/time/time.h" #include "build/build_config.h" +#include "build/buildflag.h" +#include "media/media_features.h" #include "media/remoting/remoting_cdm.h" #include "media/remoting/remoting_cdm_context.h" @@ -128,11 +130,13 @@ UpdateAndMaybeSwitch(ENABLED_BY_PAGE, DISABLED_BY_PAGE); } +#if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC) base::WeakPtr<RpcBroker> RendererController::GetRpcBroker() const { DCHECK(thread_checker_.CalledOnValidThread()); return session_->rpc_broker()->GetWeakPtr(); } +#endif void RendererController::StartDataPipe( std::unique_ptr<mojo::DataPipe> audio_data_pipe,
diff --git a/media/remoting/renderer_controller.h b/media/remoting/renderer_controller.h index 3a978f0..d721af3 100644 --- a/media/remoting/renderer_controller.h +++ b/media/remoting/renderer_controller.h
@@ -11,7 +11,9 @@ #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/timer/timer.h" +#include "build/buildflag.h" #include "media/base/media_observer.h" +#include "media/media_features.h" #include "media/remoting/metrics.h" #include "media/remoting/shared_session.h" @@ -68,7 +70,9 @@ // Used by CourierRenderer to query the session state. SharedSession* session() const { return session_.get(); } +#if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC) base::WeakPtr<RpcBroker> GetRpcBroker() const; +#endif // Called by CourierRenderer when it encountered a fatal error. This will // cause remoting to shut down and never start back up for the lifetime of
diff --git a/media/remoting/shared_session.cc b/media/remoting/shared_session.cc index b27119c..b3909038 100644 --- a/media/remoting/shared_session.cc +++ b/media/remoting/shared_session.cc
@@ -6,15 +6,24 @@ #include "base/bind.h" #include "base/logging.h" -#include "media/remoting/proto_utils.h" +#include "build/buildflag.h" +#include "media/media_features.h" + +#if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC) +#include "media/remoting/proto_utils.h" // nogncheck +#endif namespace media { namespace remoting { SharedSession::SharedSession(mojom::RemotingSourceRequest source_request, mojom::RemoterPtr remoter) +#if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC) : rpc_broker_(base::Bind(&SharedSession::SendMessageToSink, base::Unretained(this))), +#else + : +#endif binding_(this, std::move(source_request)), remoter_(std::move(remoter)) { DCHECK(remoter_); @@ -123,13 +132,16 @@ void SharedSession::OnMessageFromSink(const std::vector<uint8_t>& message) { DCHECK(thread_checker_.CalledOnValidThread()); +#if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC) std::unique_ptr<pb::RpcMessage> rpc(new pb::RpcMessage()); if (!rpc->ParseFromArray(message.data(), message.size())) { VLOG(1) << "corrupted Rpc message"; Shutdown(); return; } + rpc_broker_.ProcessMessageFromRemote(std::move(rpc)); +#endif } void SharedSession::UpdateAndNotifyState(SessionState state) {
diff --git a/media/remoting/shared_session.h b/media/remoting/shared_session.h index 5a4a4f8..5d222bc0 100644 --- a/media/remoting/shared_session.h +++ b/media/remoting/shared_session.h
@@ -10,10 +10,15 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" +#include "build/buildflag.h" +#include "media/media_features.h" #include "media/mojo/interfaces/remoting.mojom.h" -#include "media/remoting/rpc_broker.h" #include "mojo/public/cpp/bindings/binding.h" +#if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC) +#include "media/remoting/rpc_broker.h" // nogncheck +#endif + namespace media { namespace remoting { @@ -126,7 +131,9 @@ void AddClient(Client* client); void RemoveClient(Client* client); +#if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC) RpcBroker* rpc_broker() { return &rpc_broker_; } +#endif void EstimateTransmissionCapacity( mojom::Remoter::EstimateTransmissionCapacityCallback callback); @@ -142,8 +149,10 @@ // Callback from RpcBroker when sending message to remote sink. void SendMessageToSink(std::unique_ptr<std::vector<uint8_t>> message); +#if BUILDFLAG(ENABLE_MEDIA_REMOTING_RPC) // Handles dispatching of incoming and outgoing RPC messages. RpcBroker rpc_broker_; +#endif const mojo::Binding<mojom::RemotingSource> binding_; const mojom::RemoterPtr remoter_;
diff --git a/mojo/edk/system/watch.cc b/mojo/edk/system/watch.cc index b629f90f..63d8beb5 100644 --- a/mojo/edk/system/watch.cc +++ b/mojo/edk/system/watch.cc
@@ -25,12 +25,8 @@ bool allowed_to_call_callback) { AssertWatcherLockAcquired(); - // TODO(crbug.com/740044): Remove this CHECK. - CHECK(this); - // NOTE: This method must NEVER call into |dispatcher_| directly, because it // may be called while |dispatcher_| holds a lock. - MojoResult rv = MOJO_RESULT_SHOULD_WAIT; RequestContext* const request_context = RequestContext::current(); const bool notify_success = @@ -59,9 +55,6 @@ } void Watch::Cancel() { - // TODO(crbug.com/740044): Remove this CHECK. - CHECK(this); - RequestContext::current()->AddWatchCancelFinalizer(this); } @@ -71,13 +64,13 @@ // We hold the lock through invocation to ensure that only one notification // callback runs for this context at any given time. base::AutoLock lock(notification_lock_); - if (result == MOJO_RESULT_CANCELLED) { - // Make sure cancellation is the last notification we dispatch. - DCHECK(!is_cancelled_); - is_cancelled_ = true; - } else if (is_cancelled_) { + + // Ensure that no notifications are dispatched beyond cancellation. + if (is_cancelled_) return; - } + + if (result == MOJO_RESULT_CANCELLED) + is_cancelled_ = true; // NOTE: This will acquire |watcher_|'s internal lock. It's safe because a // thread can only enter InvokeCallback() from within a RequestContext
diff --git a/mojo/edk/system/watcher_dispatcher.cc b/mojo/edk/system/watcher_dispatcher.cc index 5fbaef34..cbef5b5 100644 --- a/mojo/edk/system/watcher_dispatcher.cc +++ b/mojo/edk/system/watcher_dispatcher.cc
@@ -47,9 +47,6 @@ watch = std::move(it->second); - // TODO(crbug.com/740044): Remove this CHECK. - CHECK(watch); - // Wipe out all state associated with the closed dispatcher. watches_.erase(watch->context()); ready_watches_.erase(watch.get()); @@ -97,7 +94,8 @@ std::map<uintptr_t, scoped_refptr<Watch>> watches; { base::AutoLock lock(lock_); - DCHECK(!closed_); + if (closed_) + return MOJO_RESULT_INVALID_ARGUMENT; closed_ = true; std::swap(watches, watches_); watched_handles_.clear(); @@ -122,13 +120,19 @@ // after we've updated all our own relevant state and released |lock_|. { base::AutoLock lock(lock_); - - // TODO(crbug.com/740044): Remove this CHECK. - CHECK(!closed_); + if (closed_) + return MOJO_RESULT_INVALID_ARGUMENT; if (watches_.count(context) || watched_handles_.count(dispatcher.get())) return MOJO_RESULT_ALREADY_EXISTS; + // TODO(crbug.com/740044): Remove this. Checking to see if |lock_| is + // somehow getting released by someone else while this block is running. + // Despite the documentation on base::Lock::Try, the behavior is consistent + // and safe across all platforms when called on a thread which already holds + // the lock. + CHECK(!lock_.Try()); + scoped_refptr<Watch> watch = new Watch(this, dispatcher, context, signals, condition); watches_.insert({context, watch}); @@ -147,21 +151,17 @@ return rv; } - // TODO(crbug.com/740044): Perhaps the crash is caused by a racy use of - // watchers, which - while incorrect - should not in fact be able to crash at - // this layer. - // - // Hypothesis is that two threads are racing with one adding a watch and one - // closing the watcher handle. If the watcher handle is closed immediately - // before the AddWatcherRef() call above, |dispatcher| can retain an invalid - // pointer to this WatcherDispatcher indefinitely, leading to an eventual UAF - // if and when it tries to dispatch a notification. - // - // If such a race is indeed the sole source of crashes, all subsequent crash - // reports which would have come from Watch::NotifyState etc should instead - // fail the CHECK below. - base::AutoLock lock(lock_); - CHECK(!closed_); + bool remove_now; + { + // If we've been closed already, there's a chance our closure raced with + // the call to AddWatcherRef() above. In that case we want to ensure we've + // removed our ref from |dispatcher|. Note that this may in turn race + // with normal removal, but that's fine. + base::AutoLock lock(lock_); + remove_now = closed_; + } + if (remove_now) + dispatcher->RemoveWatcherRef(this, context); return MOJO_RESULT_OK; } @@ -172,6 +172,8 @@ scoped_refptr<Watch> watch; { base::AutoLock lock(lock_); + if (closed_) + return MOJO_RESULT_INVALID_ARGUMENT; auto it = watches_.find(context); if (it == watches_.end()) return MOJO_RESULT_NOT_FOUND; @@ -179,11 +181,6 @@ watches_.erase(it); } - // TODO(crbug.com/740044): Remove these CHECKs. - CHECK(watch); - CHECK(watch->dispatcher()); - CHECK(this); - // Mark the watch as cancelled so no further notifications get through. watch->Cancel(); @@ -218,6 +215,8 @@ (!ready_contexts || !ready_results || !ready_signals_states)) { return MOJO_RESULT_INVALID_ARGUMENT; } + if (closed_) + return MOJO_RESULT_INVALID_ARGUMENT; if (watched_handles_.empty()) return MOJO_RESULT_NOT_FOUND; @@ -261,10 +260,7 @@ return MOJO_RESULT_FAILED_PRECONDITION; } -WatcherDispatcher::~WatcherDispatcher() { - // TODO(crbug.com/740044): Remove this. - CHECK(closed_); -} +WatcherDispatcher::~WatcherDispatcher() = default; } // namespace edk } // namespace mojo
diff --git a/mojo/edk/system/watcher_unittest.cc b/mojo/edk/system/watcher_unittest.cc index 9987e483..92484c4 100644 --- a/mojo/edk/system/watcher_unittest.cc +++ b/mojo/edk/system/watcher_unittest.cc
@@ -12,6 +12,7 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/rand_util.h" #include "base/synchronization/waitable_event.h" #include "base/threading/platform_thread.h" #include "base/threading/simple_thread.h" @@ -1722,6 +1723,126 @@ EXPECT_EQ(MOJO_RESULT_OK, MojoClose(a)); } +base::Closure g_do_random_thing_callback; + +void ReadAllMessages(uintptr_t context, + MojoResult result, + MojoHandleSignalsState state, + MojoWatcherNotificationFlags flags) { + if (result == MOJO_RESULT_OK) { + MojoHandle handle = static_cast<MojoHandle>(context); + MojoMessageHandle message; + while (MojoReadMessage(handle, &message, MOJO_READ_MESSAGE_FLAG_NONE) == + MOJO_RESULT_OK) { + MojoDestroyMessage(message); + } + } + + constexpr size_t kNumRandomThingsToDoOnNotify = 5; + for (size_t i = 0; i < kNumRandomThingsToDoOnNotify; ++i) + g_do_random_thing_callback.Run(); +} + +MojoHandle RandomHandle(MojoHandle* handles, size_t size) { + return handles[base::RandInt(0, static_cast<int>(size) - 1)]; +} + +void DoRandomThing(MojoHandle* watchers, + size_t num_watchers, + MojoHandle* watched_handles, + size_t num_watched_handles) { + switch (base::RandInt(0, 10)) { + case 0: + MojoClose(RandomHandle(watchers, num_watchers)); + break; + case 1: + MojoClose(RandomHandle(watched_handles, num_watched_handles)); + break; + case 2: + case 3: + case 4: { + MojoMessageHandle message; + ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessage(&message)); + ASSERT_EQ(MOJO_RESULT_OK, + MojoAttachMessageContext(message, 1, nullptr, nullptr)); + MojoWriteMessage(RandomHandle(watched_handles, num_watched_handles), + message, MOJO_WRITE_MESSAGE_FLAG_NONE); + break; + } + case 5: + case 6: { + MojoHandle w = RandomHandle(watchers, num_watchers); + MojoHandle h = RandomHandle(watched_handles, num_watched_handles); + MojoWatch(w, h, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_WATCH_CONDITION_SATISFIED, static_cast<uintptr_t>(h)); + break; + } + case 7: + case 8: { + uint32_t num_ready_contexts = 1; + uintptr_t ready_context; + MojoResult ready_result; + MojoHandleSignalsState ready_state; + if (MojoArmWatcher(RandomHandle(watchers, num_watchers), + &num_ready_contexts, &ready_context, &ready_result, + &ready_state) == MOJO_RESULT_FAILED_PRECONDITION && + ready_result == MOJO_RESULT_OK) { + ReadAllMessages(ready_context, ready_result, ready_state, 0); + } + break; + } + case 9: + case 10: { + MojoHandle w = RandomHandle(watchers, num_watchers); + MojoHandle h = RandomHandle(watched_handles, num_watched_handles); + MojoCancelWatch(w, static_cast<uintptr_t>(h)); + break; + } + default: + NOTREACHED(); + break; + } +} + +TEST_F(WatcherTest, ConcurrencyStressTest) { + // Regression test for https://crbug.com/740044. Exercises racy usage of the + // watcher API to weed out potential crashes. + + constexpr size_t kNumWatchers = 50; + constexpr size_t kNumWatchedHandles = 50; + static_assert(kNumWatchedHandles % 2 == 0, "Invalid number of test handles."); + + constexpr size_t kNumThreads = 10; + static constexpr size_t kNumOperationsPerThread = 400; + + MojoHandle watchers[kNumWatchers]; + MojoHandle watched_handles[kNumWatchedHandles]; + g_do_random_thing_callback = + base::Bind(&DoRandomThing, watchers, kNumWatchers, watched_handles, + kNumWatchedHandles); + + for (size_t i = 0; i < kNumWatchers; ++i) + MojoCreateWatcher(&ReadAllMessages, &watchers[i]); + for (size_t i = 0; i < kNumWatchedHandles; i += 2) + CreateMessagePipe(&watched_handles[i], &watched_handles[i + 1]); + + std::unique_ptr<ThreadedRunner> threads[kNumThreads]; + auto runner_callback = base::Bind([]() { + for (size_t i = 0; i < kNumOperationsPerThread; ++i) + g_do_random_thing_callback.Run(); + }); + for (size_t i = 0; i < kNumThreads; ++i) { + threads[i] = base::MakeUnique<ThreadedRunner>(runner_callback); + threads[i]->Start(); + } + for (size_t i = 0; i < kNumThreads; ++i) + threads[i]->Join(); + for (size_t i = 0; i < kNumWatchers; ++i) + MojoClose(watchers[i]); + for (size_t i = 0; i < kNumWatchedHandles; ++i) + MojoClose(watched_handles[i]); +} + } // namespace } // namespace edk } // namespace mojo
diff --git a/net/BUILD.gn b/net/BUILD.gn index 2dd67ff..99b950b 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -3610,6 +3610,10 @@ "data/url_request_unittest/BullRunSpeech.txt", "data/url_request_unittest/content-type-normalization.html", "data/url_request_unittest/content-type-normalization.html.mock-http-headers", + "data/url_request_unittest/expect-ct-header-multiple.html", + "data/url_request_unittest/expect-ct-header-multiple.html.mock-http-headers", + "data/url_request_unittest/expect-ct-header-preload.html", + "data/url_request_unittest/expect-ct-header-preload.html.mock-http-headers", "data/url_request_unittest/expect-ct-header.html", "data/url_request_unittest/expect-ct-header.html.mock-http-headers", "data/url_request_unittest/filedir-sentinel",
diff --git a/chrome/test/data/extensions/bookmark_apps/url_handlers/in_scope/index.html b/net/data/url_request_unittest/expect-ct-header-multiple.html similarity index 100% rename from chrome/test/data/extensions/bookmark_apps/url_handlers/in_scope/index.html rename to net/data/url_request_unittest/expect-ct-header-multiple.html
diff --git a/net/data/url_request_unittest/expect-ct-header-multiple.html.mock-http-headers b/net/data/url_request_unittest/expect-ct-header-multiple.html.mock-http-headers new file mode 100644 index 0000000..0f7352d --- /dev/null +++ b/net/data/url_request_unittest/expect-ct-header-multiple.html.mock-http-headers
@@ -0,0 +1,6 @@ +HTTP/1.1 200 OK +Cache-Control: private +Content-Type: text/html; charset=ISO-8859-1 +Expect-CT: max-age=100 +Expect-CT: enforce +Expect-CT: report-uri=https://example.test \ No newline at end of file
diff --git a/chrome/test/data/extensions/bookmark_apps/url_handlers/in_scope/index.html b/net/data/url_request_unittest/expect-ct-header-preload.html similarity index 100% copy from chrome/test/data/extensions/bookmark_apps/url_handlers/in_scope/index.html copy to net/data/url_request_unittest/expect-ct-header-preload.html
diff --git a/net/data/url_request_unittest/expect-ct-header-preload.html.mock-http-headers b/net/data/url_request_unittest/expect-ct-header-preload.html.mock-http-headers new file mode 100644 index 0000000..3e116582 --- /dev/null +++ b/net/data/url_request_unittest/expect-ct-header-preload.html.mock-http-headers
@@ -0,0 +1,4 @@ +HTTP/1.1 200 OK +Cache-Control: private +Content-Type: text/html; charset=ISO-8859-1 +Expect-CT: preload
diff --git a/net/data/url_request_unittest/expect-ct-header.html.mock-http-headers b/net/data/url_request_unittest/expect-ct-header.html.mock-http-headers index 3e116582..6fe4c4cab 100644 --- a/net/data/url_request_unittest/expect-ct-header.html.mock-http-headers +++ b/net/data/url_request_unittest/expect-ct-header.html.mock-http-headers
@@ -1,4 +1,4 @@ HTTP/1.1 200 OK Cache-Control: private Content-Type: text/html; charset=ISO-8859-1 -Expect-CT: preload +Expect-CT: max-age=100, enforce, report-uri=https://example.test \ No newline at end of file
diff --git a/net/http/transport_security_state.h b/net/http/transport_security_state.h index 5e75551..b4bab0db 100644 --- a/net/http/transport_security_state.h +++ b/net/http/transport_security_state.h
@@ -580,7 +580,7 @@ FRIEND_TEST_ALL_PREFIXES(HttpSecurityHeadersTest, UpdateDynamicPKPOnly); FRIEND_TEST_ALL_PREFIXES(HttpSecurityHeadersTest, UpdateDynamicPKPMaxAge0); FRIEND_TEST_ALL_PREFIXES(HttpSecurityHeadersTest, NoClobberPins); - FRIEND_TEST_ALL_PREFIXES(URLRequestTestHTTP, ExpectCTHeader); + FRIEND_TEST_ALL_PREFIXES(URLRequestTestHTTP, PreloadExpectCTHeader); typedef std::map<std::string, STSState> STSStateMap; typedef std::map<std::string, PKPState> PKPStateMap;
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 21d60a8..27844b29 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -872,10 +872,9 @@ return; } - // Only process the first Expect-CT header value. HttpResponseHeaders* headers = GetResponseHeaders(); std::string value; - if (headers->EnumerateHeader(nullptr, "Expect-CT", &value)) { + if (headers->GetNormalizedHeader("Expect-CT", &value)) { security_state->ProcessExpectCTHeader( value, HostPortPair::FromURL(request_info_.url), ssl_info); }
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 78a00de..5f9da873 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -44,6 +44,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/test/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "build/buildflag.h" @@ -6819,8 +6820,8 @@ ct::CertPolicyCompliance default_result_; }; -// Tests that Expect CT headers are processed correctly. -TEST_F(URLRequestTestHTTP, ExpectCTHeader) { +// Tests that Expect CT headers for the preload list are processed correctly. +TEST_F(URLRequestTestHTTP, PreloadExpectCTHeader) { #if !BUILDFLAG(INCLUDE_TRANSPORT_SECURITY_STATE_PRELOAD_LIST) SetTransportSecurityStateSourceForTesting(&test0::kHSTSSource); #endif @@ -6868,7 +6869,7 @@ // Now send a request to trigger the violation. TestDelegate d; - GURL url = https_test_server.GetURL("/expect-ct-header.html"); + GURL url = https_test_server.GetURL("/expect-ct-header-preload.html"); GURL::Replacements replace_host; replace_host.SetHostStr(kExpectCTStaticHostname); url = url.ReplaceComponents(replace_host); @@ -6879,6 +6880,130 @@ EXPECT_EQ(1u, reporter.num_failures()); } + +// Tests that Expect CT HTTP headers are processed correctly. +TEST_F(URLRequestTestHTTP, ExpectCTHeader) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + TransportSecurityState::kDynamicExpectCTFeature); + + EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_test_server.SetSSLConfig( + net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN); + https_test_server.ServeFilesFromSourceDirectory( + base::FilePath(kTestFilePath)); + ASSERT_TRUE(https_test_server.Start()); + + MockExpectCTReporter reporter; + TransportSecurityState transport_security_state; + transport_security_state.SetExpectCTReporter(&reporter); + + // Set up a MockCertVerifier to accept the certificate that the server sends. + scoped_refptr<X509Certificate> cert = https_test_server.GetCertificate(); + ASSERT_TRUE(cert); + MockCertVerifier cert_verifier; + CertVerifyResult verify_result; + verify_result.verified_cert = cert; + verify_result.is_issued_by_known_root = true; + cert_verifier.AddResultForCert(cert.get(), verify_result, OK); + + // Set up a DoNothingCTVerifier and MockCTPolicyEnforcer to simulate CT + // compliance. + DoNothingCTVerifier ct_verifier; + MockCTPolicyEnforcer ct_policy_enforcer; + ct_policy_enforcer.set_default_result( + ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS); + + TestNetworkDelegate network_delegate; + // Use a MockHostResolver (which by default maps all hosts to + // 127.0.0.1). + MockHostResolver host_resolver; + TestURLRequestContext context(true); + context.set_host_resolver(&host_resolver); + context.set_transport_security_state(&transport_security_state); + context.set_network_delegate(&network_delegate); + context.set_cert_verifier(&cert_verifier); + context.set_cert_transparency_verifier(&ct_verifier); + context.set_ct_policy_enforcer(&ct_policy_enforcer); + context.Init(); + + // Now send a request to trigger the header processing. + TestDelegate d; + GURL url = https_test_server.GetURL("/expect-ct-header.html"); + std::unique_ptr<URLRequest> request(context.CreateRequest( + url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + request->Start(); + base::RunLoop().Run(); + + TransportSecurityState::ExpectCTState state; + ASSERT_TRUE( + transport_security_state.GetDynamicExpectCTState(url.host(), &state)); + EXPECT_TRUE(state.enforce); + EXPECT_EQ(GURL("https://example.test"), state.report_uri); +} + +// Tests that if multiple Expect CT HTTP headers are sent, they are all +// processed. +TEST_F(URLRequestTestHTTP, MultipleExpectCTHeaders) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + TransportSecurityState::kDynamicExpectCTFeature); + + EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS); + https_test_server.SetSSLConfig( + net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN); + https_test_server.ServeFilesFromSourceDirectory( + base::FilePath(kTestFilePath)); + ASSERT_TRUE(https_test_server.Start()); + + MockExpectCTReporter reporter; + TransportSecurityState transport_security_state; + transport_security_state.SetExpectCTReporter(&reporter); + + // Set up a MockCertVerifier to accept the certificate that the server sends. + scoped_refptr<X509Certificate> cert = https_test_server.GetCertificate(); + ASSERT_TRUE(cert); + MockCertVerifier cert_verifier; + CertVerifyResult verify_result; + verify_result.verified_cert = cert; + verify_result.is_issued_by_known_root = true; + cert_verifier.AddResultForCert(cert.get(), verify_result, OK); + + // Set up a DoNothingCTVerifier and MockCTPolicyEnforcer to simulate CT + // compliance. + DoNothingCTVerifier ct_verifier; + MockCTPolicyEnforcer ct_policy_enforcer; + ct_policy_enforcer.set_default_result( + ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS); + + TestNetworkDelegate network_delegate; + // Use a MockHostResolver (which by default maps all hosts to + // 127.0.0.1). + MockHostResolver host_resolver; + TestURLRequestContext context(true); + context.set_host_resolver(&host_resolver); + context.set_transport_security_state(&transport_security_state); + context.set_network_delegate(&network_delegate); + context.set_cert_verifier(&cert_verifier); + context.set_cert_transparency_verifier(&ct_verifier); + context.set_ct_policy_enforcer(&ct_policy_enforcer); + context.Init(); + + // Now send a request to trigger the header processing. + TestDelegate d; + GURL url = https_test_server.GetURL("/expect-ct-header-multiple.html"); + std::unique_ptr<URLRequest> request(context.CreateRequest( + url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + request->Start(); + base::RunLoop().Run(); + + TransportSecurityState::ExpectCTState state; + ASSERT_TRUE( + transport_security_state.GetDynamicExpectCTState(url.host(), &state)); + EXPECT_TRUE(state.enforce); + EXPECT_EQ(GURL("https://example.test"), state.report_uri); +} + #endif // !defined(OS_IOS) #if BUILDFLAG(ENABLE_REPORTING)
diff --git a/ppapi/features/features.gni b/ppapi/features/features.gni index ac17e1f..560d1ec 100644 --- a/ppapi/features/features.gni +++ b/ppapi/features/features.gni
@@ -7,5 +7,5 @@ import("//build/config/features.gni") declare_args() { - enable_plugins = !is_android && !is_ios && !is_chromecast + enable_plugins = !is_android && !is_ios && !is_chromecast && !is_fuchsia }
diff --git a/printing/features/features.gni b/printing/features/features.gni index a41202a2..b3d6967 100644 --- a/printing/features/features.gni +++ b/printing/features/features.gni
@@ -7,11 +7,11 @@ declare_args() { # Enable basic printing support and UI. - enable_basic_printing = !is_chromecast && !is_ios + enable_basic_printing = !is_chromecast && !is_ios && !is_fuchsia # Enable printing with print preview. It does not imply # enable_basic_printing. It's possible to build Chrome with preview only. - enable_print_preview = !is_android && !is_chromecast && !is_ios + enable_print_preview = !is_android && !is_chromecast && !is_ios && !is_fuchsia - use_cups = (is_desktop_linux || is_mac) && !is_chromecast + use_cups = (is_desktop_linux || is_mac) && !is_chromecast && !is_fuchsia }
diff --git a/remoting/client/software_video_renderer.cc b/remoting/client/software_video_renderer.cc index 535c0a12..4d79004 100644 --- a/remoting/client/software_video_renderer.cc +++ b/remoting/client/software_video_renderer.cc
@@ -159,7 +159,7 @@ base::Passed(&frame)), base::Bind(&SoftwareVideoRenderer::RenderFrame, weak_factory_.GetWeakPtr(), base::Passed(&frame_stats), - done_runner.Release())); + base::AdaptCallbackForRepeating(done_runner.Release()))); } void SoftwareVideoRenderer::RenderFrame(
diff --git a/services/device/time_zone_monitor/BUILD.gn b/services/device/time_zone_monitor/BUILD.gn index 14cba6d..05dd15c 100644 --- a/services/device/time_zone_monitor/BUILD.gn +++ b/services/device/time_zone_monitor/BUILD.gn
@@ -51,6 +51,10 @@ if (is_mac) { libs = [ "Foundation.framework" ] } + + if (is_fuchsia) { + sources += [ "time_zone_monitor_fuchsia.cc" ] + } } if (is_android) {
diff --git a/services/device/time_zone_monitor/time_zone_monitor_fuchsia.cc b/services/device/time_zone_monitor/time_zone_monitor_fuchsia.cc new file mode 100644 index 0000000..71594fa1 --- /dev/null +++ b/services/device/time_zone_monitor/time_zone_monitor_fuchsia.cc
@@ -0,0 +1,36 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/device/time_zone_monitor/time_zone_monitor.h" + +#include <memory> + +#include "base/logging.h" +#include "base/memory/ptr_util.h" + +namespace device { +namespace { + +// TODO(fuchsia): Implement this. crbug.com/750934 +class TimeZoneMonitorFuchsia : public TimeZoneMonitor { + public: + TimeZoneMonitorFuchsia() = default; + ~TimeZoneMonitorFuchsia() override = default; + + private: + DISALLOW_COPY_AND_ASSIGN(TimeZoneMonitorFuchsia); +}; + +} // namespace + +// static +std::unique_ptr<TimeZoneMonitor> TimeZoneMonitor::Create( + scoped_refptr<base::SequencedTaskRunner> file_task_runner) { + // TODO(fuchsia): Implement this. crbug.com/750934 + NOTIMPLEMENTED(); + + return base::MakeUnique<TimeZoneMonitorFuchsia>(); +} + +} // namespace device
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index ade91ab..4ec4597 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -216,6 +216,10 @@ #define SK_SUPPORT_LEGACY_DELTA_AA #endif +#ifndef SK_SUPPORT_LEGACY_ROTATED_SHADERS +#define SK_SUPPORT_LEGACY_ROTATED_SHADERS +#endif + ///////////////////////// Imported from BUILD.gn and skia_common.gypi /* In some places Skia can use static initializers for global initialization,
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index cbec29b..63838cdd 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -320,10 +320,6 @@ "label": "//:chromium_builder_perf", "type": "additional_compile_target", }, - "chromium_swarm_tests": { - "label": "//:chromium_swarm_tests", - "type": "additional_compile_target", - }, "chromiumos_preflight": { "label": "//:chromiumos_preflight", "type": "additional_compile_target",
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py index 5428375..5a7e2f7 100755 --- a/testing/buildbot/manage.py +++ b/testing/buildbot/manage.py
@@ -91,7 +91,6 @@ 'chrome_official_builder_no_unittests', 'chromium_builder_asan', 'chromium_builder_perf', - 'chromium_swarm_tests', 'chromiumos_preflight', 'mini_installer', 'next_version_mini_installer',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 167b40d..cd9c4e0 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1346,8 +1346,8 @@ { "name": "MaxDelayable4", "params": { - "MaxBDPKBits1": "10", - "MaxBDPKBits2": "5000", + "MaxBDPKbits1": "10", + "MaxBDPKbits2": "5000", "MaxDelayableRequests1": "10", "MaxDelayableRequests2": "4", "MaxEffectiveConnectionType": "3G"
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 961d4b8..dbc5b4f 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -297,7 +297,6 @@ crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floating-replaced-height-008.xht [ Skip ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-005.xht [ Failure ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-028.xht [ Failure ] -crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-029.xht [ Failure ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-036.xht [ Failure ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-108.xht [ Skip ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-109.xht [ Skip ] @@ -310,16 +309,8 @@ crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-131.xht [ Skip ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-137.xht [ Skip ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-143.xht [ Failure ] -crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/margin-collapse-018.xht [ Failure ] -crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/margin-collapse-027.xht [ Failure ] -crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/margin-collapse-033.xht [ Failure ] -crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/margin-collapse-034.xht [ Failure ] -crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/margin-collapse-035.xht [ Failure ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/margin-collapse-157.xht [ Failure ] crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/margin-collapse-clear-008.xht [ Failure ] -crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/margin-collapse-clear-012.xht [ Failure ] -crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/margin-collapse-clear-013.xht [ Failure ] -crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/margin-collapse-clear-014.xht [ Failure ] # Regressions while changing zero-block-size float behaviour. crbug.com/635619 virtual/layout_ng/external/wpt/css/CSS2/floats-clear/floats-009.xht [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 147fbd9c..a3cc876 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -2515,6 +2515,12 @@ {} ] ], + "fullscreen/model/move-to-inactive-document-manual.html": [ + [ + "/fullscreen/model/move-to-inactive-document-manual.html", + {} + ] + ], "fullscreen/model/remove-child-manual.html": [ [ "/fullscreen/model/remove-child-manual.html", @@ -33947,6 +33953,18 @@ {} ] ], + "css/css-grid-1/implicit-grids/grid-support-grid-auto-columns-rows-002.html": [ + [ + "/css/css-grid-1/implicit-grids/grid-support-grid-auto-columns-rows-002.html", + [ + [ + "/css/css-grid-1/reference/grid-support-grid-auto-columns-rows-002-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-grid-1/layout-algorithm/grid-layout-free-space-unit.html": [ [ "/css/css-grid-1/layout-algorithm/grid-layout-free-space-unit.html", @@ -69365,6 +69383,16 @@ {} ] ], + "content-security-policy/navigation/support/test_csp_self_window.sub.html": [ + [ + {} + ] + ], + "content-security-policy/navigation/support/test_csp_self_window.sub.html.sub.headers": [ + [ + {} + ] + ], "content-security-policy/nonce-hiding/script-nonces-hidden.tentative.html.headers": [ [ {} @@ -75860,6 +75888,11 @@ {} ] ], + "css/css-grid-1/reference/grid-support-grid-auto-columns-rows-002-ref.html": [ + [ + {} + ] + ], "css/css-grid-1/reference/grid-text-green-margin-no-collapse-ref.html": [ [ {} @@ -86165,6 +86198,16 @@ {} ] ], + "dom/traversal/NodeIterator-expected.txt": [ + [ + {} + ] + ], + "dom/traversal/TreeWalker-expected.txt": [ + [ + {} + ] + ], "dom/traversal/traversal-support.js": [ [ {} @@ -102390,6 +102433,11 @@ {} ] ], + "orientation-sensor/OrientationSensor.https-expected.txt": [ + [ + {} + ] + ], "orientation-sensor/idlharness.https-expected.txt": [ [ {} @@ -102550,6 +102598,11 @@ {} ] ], + "payment-request/payment-request-ctor-currency-code-checks.https-expected.txt": [ + [ + {} + ] + ], "payment-request/payment-request-id.https-expected.txt": [ [ {} @@ -122971,6 +123024,12 @@ {} ] ], + "content-security-policy/navigation/javascript-url-navigation-inherits-csp.html": [ + [ + "/content-security-policy/navigation/javascript-url-navigation-inherits-csp.html", + {} + ] + ], "content-security-policy/navigation/to-javascript-url-frame-src.html": [ [ "/content-security-policy/navigation/to-javascript-url-frame-src.html", @@ -138967,6 +139026,12 @@ {} ] ], + "html/semantics/selectors/pseudo-classes/required-optional-hidden.html": [ + [ + "/html/semantics/selectors/pseudo-classes/required-optional-hidden.html", + {} + ] + ], "html/semantics/selectors/pseudo-classes/required-optional.html": [ [ "/html/semantics/selectors/pseudo-classes/required-optional.html", @@ -174767,7 +174832,7 @@ "support" ], "./lint.whitelist": [ - "88b6f9f4e14fc72be06059f49a152801c9b353a9", + "03e30970dd6e2a62a999b8aa1592a88c4cfc84be", "support" ], "./update-built-tests.sh": [ @@ -185406,6 +185471,18 @@ "2553698b40d91f95f33bb14e7bd906d665b0381a", "testharness" ], + "content-security-policy/navigation/javascript-url-navigation-inherits-csp.html": [ + "bb01b98b633fe5ffb79b1b4e0943a77b85a11057", + "testharness" + ], + "content-security-policy/navigation/support/test_csp_self_window.sub.html": [ + "df2273c83ff0d663fdcd46d91a0eb0e8a743b49b", + "support" + ], + "content-security-policy/navigation/support/test_csp_self_window.sub.html.sub.headers": [ + "44b5dae4b9d0c5570e79d4fed8a7e8a709470c95", + "support" + ], "content-security-policy/navigation/to-javascript-url-frame-src.html": [ "3070ea56bcb7dc454d7bc252377f0dc5bcb03c7c", "testharness" @@ -204434,6 +204511,10 @@ "85a397623ccb6b2ced1450af19f0eaf3a2f6df22", "reftest" ], + "css/css-grid-1/implicit-grids/grid-support-grid-auto-columns-rows-002.html": [ + "909c91b995daafc31a6fa9f6989dc78c892840e3", + "reftest" + ], "css/css-grid-1/layout-algorithm/grid-layout-free-space-unit.html": [ "5873efcda9c17e48a8437a62bf6871cbf96bdc46", "reftest" @@ -204510,6 +204591,10 @@ "ff487f266aa067949899506059e19d4b8fbf429c", "support" ], + "css/css-grid-1/reference/grid-support-grid-auto-columns-rows-002-ref.html": [ + "15153e77178d8cd869839e9a449e9beb130af023", + "support" + ], "css/css-grid-1/reference/grid-text-green-margin-no-collapse-ref.html": [ "feb53485e24aeaf9a5f27be5e42cc4a6fc5b8df0", "support" @@ -224375,7 +224460,7 @@ "support" ], "dom/nodes/Document-createEvent-expected.txt": [ - "482ce246d83fad12b60c5d9e65c65fca2cd5bf7a", + "7a791e90bb1dc2cda4666387c021f226f4012b44", "support" ], "dom/nodes/Document-createEvent.html": [ @@ -224519,7 +224604,7 @@ "testharness" ], "dom/nodes/Element-classlist.html": [ - "c197df35960b77a7794eed10a1a927867a6658f4", + "4ff46caa5ddf71a0b91ddf921882114d0c89d9d3", "testharness" ], "dom/nodes/Element-closest-expected.txt": [ @@ -225218,6 +225303,10 @@ "cd87e7ecb902e44ec5e62a29f95331e614f1e221", "testharness" ], + "dom/traversal/NodeIterator-expected.txt": [ + "9e52e8f0cf916dc8968e30c08d067d751ccdb40a", + "support" + ], "dom/traversal/NodeIterator-removal.html": [ "94eba47487961f5d3e5eecf3c44d3d7b993d95d4", "testharness" @@ -225238,6 +225327,10 @@ "a8029dd7b8774674dfbe40ab723e08cd666569c7", "testharness" ], + "dom/traversal/TreeWalker-expected.txt": [ + "5ccf190d92fe62eaa8c12cbda8a82c8da12b0f08", + "support" + ], "dom/traversal/TreeWalker-previousNodeLastChildReject.html": [ "78ab615dede4f1fa67e76538787e3bc32a2d6cde", "testharness" @@ -229154,6 +229247,10 @@ "818cb1b5db729db4959591dc75d4bb1ae3c7542d", "manual" ], + "fullscreen/model/move-to-inactive-document-manual.html": [ + "552d65141acc2221e8407316c02e0d4cf17db7eb", + "manual" + ], "fullscreen/model/remove-child-manual.html": [ "b1142930c6c972057213bd477cf116fcc9e7fc2a", "manual" @@ -229191,7 +229288,7 @@ "support" ], "generic-sensor/generic-sensor-tests.js": [ - "d55e585268de8d973a77b5f37c3d84bbf2ff6470", + "afe53161d26459005788e6e9e9bbc5461b3a9ea2", "support" ], "generic-sensor/idlharness-expected.txt": [ @@ -242827,7 +242924,7 @@ "testharness" ], "html/semantics/scripting-1/the-template-element/template-element/template-content.html": [ - "61432b241e8d7e2cd8d4c70f10260fd2f13371eb", + "a4d34cf0ed7b52cc9c30ad1d6b6aa322b5cfd2b4", "testharness" ], "html/semantics/scripting-1/the-template-element/template-element/template-descendant-body.html": [ @@ -242994,6 +243091,10 @@ "835c87fe2a1952890b1adc3f39981a0c1360b5be", "testharness" ], + "html/semantics/selectors/pseudo-classes/required-optional-hidden.html": [ + "f46d516f68e83556f4f7575521df65aa384961b4", + "testharness" + ], "html/semantics/selectors/pseudo-classes/required-optional.html": [ "503189428dbc44ad4cd5d9c93b22d2ea9307d89e", "testharness" @@ -254710,6 +254811,10 @@ "6948dbbdc88ffd9aa84ad5a6c822b354809561b2", "manual" ], + "orientation-sensor/OrientationSensor.https-expected.txt": [ + "edbb43576664f2fd425256b8fe7bc3ae42e2066e", + "support" + ], "orientation-sensor/OrientationSensor.https.html": [ "145b750c49bf703c68bcf4ad645448bc284d393b", "testharness" @@ -254982,6 +255087,10 @@ "847cc78f52dc5696886eedc77b2969a562caf74f", "testharness" ], + "payment-request/payment-request-ctor-currency-code-checks.https-expected.txt": [ + "9d06b666965f9ca61d2f6732cf5bad9536b3e8a7", + "support" + ], "payment-request/payment-request-ctor-currency-code-checks.https.html": [ "7efdfa3457fff90fc3f66054505dcf7a7ff4645b", "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/implicit-grids/grid-support-grid-auto-columns-rows-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/implicit-grids/grid-support-grid-auto-columns-rows-002.html new file mode 100644 index 0000000..2e90b46 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/implicit-grids/grid-support-grid-auto-columns-rows-002.html
@@ -0,0 +1,59 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Support for 'grid-auto-columns' and 'grid-auto-rows' accepting track listing as value</title> +<link rel="help" href="http://www.w3.org/TR/css-grid-1/#auto-tracks"> +<link rel="match" href="../reference/grid-support-grid-auto-columns-rows-002-ref.html"> +<link rel="author" title="Rachel Andrew" href="mailto:me@rachelandrew.co.uk" /> +<style> + #grid { + display: grid; + grid-auto-columns: 25px 50px; + grid-auto-rows: 40px 30px; + } + + #first-column-first-row { + grid-column: 1; + grid-row: 1; + background-color: purple; + } + + #second-column-first-row { + grid-column: 2; + grid-row: 1; + background-color: orange; + } + + #first-column-second-row { + grid-column: 1; + grid-row: 2; + background-color: green; + } + + #second-column-second-row { + grid-column: 2; + grid-row: 2; + background-color: pink; + } + + #first-and-second-column-third-row { + grid-column: 1 / span 2; + grid-row: 3; + background-color: silver; + } + + #third-column-all-rows { + grid-column: 3; + grid-row: 1 / span 3; + background-color: blue; + } +</style> + +<p>The test passes if it has the same visual effect as reference.</p> +<div id="grid"> + <div id="first-column-first-row"></div> + <div id="second-column-first-row"></div> + <div id="first-column-second-row"></div> + <div id="second-column-second-row"></div> + <div id="first-and-second-column-third-row"></div> + <div id="third-column-all-rows"></div> +</div> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/reference/grid-support-grid-auto-columns-rows-002-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/reference/grid-support-grid-auto-columns-rows-002-ref.html new file mode 100644 index 0000000..4a21823 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid-1/reference/grid-support-grid-auto-columns-rows-002-ref.html
@@ -0,0 +1,67 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Support for 'grid-auto-columns' and 'grid-auto-rows' properties accepting track listing as value</title> +<link rel="author" title="Rachel Andrew" href="mailto:me@rachelandrew.co.uk" /> +<style> + #grid { + position: relative; + } + + .absolute { + position: absolute; + top: 0; + left: 0; + } + + #first-column-first-row { + width: 25px; + height: 40px; + background-color: purple; + } + + #second-column-first-row { + width: 50px; + height: 40px; + left: 25px; + background-color: orange; + } + + #first-column-second-row { + width: 25px; + height: 30px; + top: 40px; + background-color: green; + } + + #second-column-second-row { + width: 50px; + height: 30px; + top: 40px; + left: 25px; + background-color: pink; + } + + #first-and-second-column-third-row { + width: 75px; + height: 40px; + top: 70px; + background-color: silver; + } + + #third-column-all-rows { + left: 75px; + height: 110px; + width: 25px; + background-color: blue; + } +</style> + +<p>The test passes if it has the same visual effect as reference.</p> +<div id="grid"> + <div class="absolute" id="first-column-first-row"></div> + <div class="absolute" id="second-column-first-row"></div> + <div class="absolute" id="first-column-second-row"></div> + <div class="absolute" id="second-column-second-row"></div> + <div class="absolute" id="first-and-second-column-third-row"></div> + <div class="absolute" id="third-column-all-rows"></div> +</div> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-classlist.html b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-classlist.html index ece938e..1c8ba2d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-classlist.html +++ b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Element-classlist.html
@@ -199,15 +199,22 @@ // add() method - function checkAdd(before, argument, after, expectedException) { + function checkAdd(before, argument, after, param) { + var expectedException = undefined; + var noop = false; + if (param == "noop") { + noop = true; + } else { + expectedException = param; + } checkModification(e, "add", argument, undefined, before, after, expectedException, desc); - // Also check force toggle - // XXX https://github.com/whatwg/dom/issues/443 - //if (!Array.isArray(argument)) { - // checkModification(e, "toggle", [argument, true], true, before, after, - // expectedException); - //} + // Also check force toggle. The only difference is that it doesn't run the + // update steps for a no-op. + if (!Array.isArray(argument)) { + checkModification(e, "toggle", [argument, true], true, before, + noop ? before : after, expectedException, desc); + } } checkAdd(null, "", null, "SyntaxError"); @@ -229,7 +236,7 @@ checkAdd("a", "a", "a"); checkAdd("aa", "AA", "aa AA"); checkAdd("a b c", "a", "a b c"); - checkAdd("a a a b", "a", "a b"); + checkAdd("a a a b", "a", "a b", "noop"); checkAdd(null, "a", "a"); checkAdd("", "a", "a"); checkAdd(" ", "a", "a"); @@ -238,7 +245,7 @@ checkAdd("a b c", "d", "a b c d"); checkAdd("a b c ", "d", "a b c d"); checkAdd(" a a b", "c", "a b c"); - checkAdd(" a a b", "a", "a b"); + checkAdd(" a a b", "a", "a b", "noop"); checkAdd("\t\n\f\r a\t\n\f\r b\t\n\f\r ", "c", "a b c"); // multiple add @@ -254,15 +261,22 @@ // remove() method - function checkRemove(before, argument, after, expectedException) { + function checkRemove(before, argument, after, param) { + var expectedException = undefined; + var noop = false; + if (param == "noop") { + noop = true; + } else { + expectedException = param; + } checkModification(e, "remove", argument, undefined, before, after, expectedException, desc); - // Also check force toggle - // XXX https://github.com/whatwg/dom/issues/443 - //if (!Array.isArray(argument)) { - // checkModification(e, "toggle", [argument, false], false, before, after, - // expectedException); - //} + // Also check force toggle. The only difference is that it doesn't run the + // update steps for a no-op. + if (!Array.isArray(argument)) { + checkModification(e, "toggle", [argument, false], false, before, + noop ? before : after, expectedException, desc); + } } checkRemove(null, "", null, "SyntaxError"); @@ -281,8 +295,8 @@ checkRemove(null, "a", null); checkRemove("", "a", ""); - checkRemove("a b c", "d", "a b c"); - checkRemove("a b c", "A", "a b c"); + checkRemove("a b c", "d", "a b c", "noop"); + checkRemove("a b c", "A", "a b c", "noop"); checkRemove(" a a a ", "a", ""); checkRemove("a b", "a", "b"); checkRemove("a b ", "a", "b"); @@ -355,24 +369,6 @@ checkToggle("", undefined, true, "undefined"); - // tests for the force argument handling - // XXX Remove these if https://github.com/whatwg/dom/issues/443 is fixed - - function checkForceToggle(before, argument, force, expectedRes, after, expectedException) { - checkModification(e, "toggle", [argument, force], expectedRes, before, - after, expectedException, desc); - } - - checkForceToggle("", "a", true, true, "a"); - checkForceToggle("a", "a", true, true, "a"); - checkForceToggle("a", "b", true, true, "a b"); - checkForceToggle("a b", "b", true, true, "a b"); - checkForceToggle("", "a", false, false, ""); - checkForceToggle("a", "a", false, false, ""); - checkForceToggle("a", "b", false, false, "a"); - checkForceToggle("a b", "b", false, false, "a"); - - // replace() method function checkReplace(before, token, newToken, after, expectedException) { checkModification(e, "replace", [token, newToken], undefined, before,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/generic-sensor-tests.js b/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/generic-sensor-tests.js index a55901e..df9ccf3 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/generic-sensor-tests.js +++ b/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/generic-sensor-tests.js
@@ -36,6 +36,7 @@ } function runGenericSensorTests(sensorType) { + const prefix = sensorType.name + ": "; async_test(t => { let sensor = new sensorType(); sensor.onreading = t.step_func_done(() => { @@ -45,7 +46,7 @@ }); sensor.onerror = t.step_func_done(unreached); sensor.start(); - }, "Test that 'onreading' is called and sensor reading is valid"); + }, prefix + "Test that 'onreading' is called and sensor reading is valid"); async_test(t => { let sensor1 = new sensorType(); @@ -67,7 +68,7 @@ sensor2.onerror = t.step_func_done(unreached); sensor1.start(); sensor2.start(); - }, "sensor reading is correct"); + }, prefix + "sensor reading is correct"); async_test(t => { let sensor = new sensorType(); @@ -85,7 +86,7 @@ sensor.stop(); }); }, 1000); - }, "sensor timestamp is updated when time passes"); + }, prefix + "sensor timestamp is updated when time passes"); async_test(t => { let sensor = new sensorType(); @@ -98,7 +99,7 @@ }); sensor.start(); assert_false(sensor.activated); - }, "Test that sensor can be successfully created and its states are correct."); + }, prefix + "Test that sensor can be successfully created and its states are correct."); test(() => { let sensor, start_return; @@ -107,7 +108,7 @@ start_return = sensor.start(); assert_equals(start_return, undefined); sensor.stop(); - }, "sensor.start() returns undefined"); + }, prefix + "sensor.start() returns undefined"); test(() => { try { @@ -120,7 +121,7 @@ } catch (e) { assert_unreached(e.name + ": " + e.message); } - }, "no exception is thrown when calling start() on already started sensor"); + }, prefix + "no exception is thrown when calling start() on already started sensor"); test(() => { let sensor, stop_return; @@ -129,7 +130,7 @@ sensor.start(); stop_return = sensor.stop(); assert_equals(stop_return, undefined); - }, "sensor.stop() returns undefined"); + }, prefix + "sensor.stop() returns undefined"); test(() => { try { @@ -142,7 +143,7 @@ } catch (e) { assert_unreached(e.name + ": " + e.message); } - }, "no exception is thrown when calling stop() on already stopped sensor"); + }, prefix + "no exception is thrown when calling stop() on already stopped sensor"); promise_test(() => { return new Promise((resolve,reject) => { @@ -169,7 +170,7 @@ } } }); - }, "throw a 'SecurityError' when constructing sensor object within iframe"); + }, prefix + "throw a 'SecurityError' when constructing sensor object within iframe"); async_test(t => { let sensor = new sensorType(); @@ -187,16 +188,18 @@ }); sensor.onerror = t.step_func_done(unreached); sensor.start(); - }, "sensor readings can not be fired on the background tab"); + }, prefix + "sensor readings can not be fired on the background tab"); } function runGenericSensorInsecureContext(sensorType) { + const prefix = sensorType.name + ": "; test(() => { assert_throws('SecurityError', () => { new sensorType(); }); - }, "throw a 'SecurityError' when construct sensor in an insecure context"); + }, prefix + "throw a 'SecurityError' when construct sensor in an insecure context"); } function runGenericSensorOnerror(sensorType) { + const prefix = sensorType.name + ": "; async_test(t => { let sensor = new sensorType(); sensor.onactivate = t.step_func_done(assert_unreached); @@ -205,5 +208,5 @@ assert_equals(event.error.name, 'NotReadableError'); }); sensor.start(); - }, "'onerror' event is fired when sensor is not supported"); + }, prefix + "'onerror' event is fired when sensor is not supported"); }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-content.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-content.html index 8ed55d0d2..b9e790da 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-content.html +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-content.html
@@ -14,64 +14,50 @@ <div id="log"></div> <script type="text/javascript"> +HTML5_ELEMENTS.forEach(function(value) { + if (value !== 'body' && value !== 'html' && value !== 'head' && value !== 'frameset') { + + test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + var element = doc.createElement(value); + template.content.appendChild(element); + var valueToTest = template.content.querySelector(value); + + doc.body.appendChild(template); + + assert_not_equals(valueToTest, null); + }, 'Template may contain ' + value + ' element'); + + } +}); + + + var parameters = []; HTML5_ELEMENTS.forEach(function(value) { if (value !== 'body' && value !== 'html' && value !== 'head' && value !== 'frameset') { - var doc = newHTMLDocument(); - var template = doc.createElement('template'); - var element = doc.createElement(value); - template.content.appendChild(element); - var valueToTest = template.content.querySelector(value); + test(function() { + var doc = newHTMLDocument(); - doc.body.appendChild(template); + if (isVoidElement(value)) { + doc.body.innerHTML = '<template><' + value + '/></template>'; + } else { + doc.body.innerHTML = '<template><' + value + '></' + value + '></template>'; + } - parameters.push([ - 'Template may contain ' + value + ' element', - valueToTest, - null - ]); + var template = doc.querySelector('template'); + var element = template.content.querySelector(value); + + assert_not_equals(element, null); + }, 'Template may contain ' + value + ' element. ' + + 'The template element and contents are added via body.innerHTML'); + } }); -generate_tests(assert_not_equals, parameters, - 'Template may contain any element, except the html element, ' - + 'the head element, the body element, or the frameset element'); - - - - -var parameters = []; - -HTML5_ELEMENTS.forEach(function(value) { - if (value !== 'body' && value !== 'html' && value !== 'head' && value !== 'frameset') { - - var doc = newHTMLDocument(); - - if (isVoidElement(value)) { - doc.body.innerHTML = '<template><' + value + '/></template>'; - } else { - doc.body.innerHTML = '<template><' + value + '></' + value + '></template>'; - } - - var template = doc.querySelector('template'); - var element = template.content.querySelector(value); - - parameters.push([ - 'Template may contain ' + value + ' element. ' - +'The template element and contents are added via body.innerHTML', - element, - null - ]); - } -}); - -generate_tests(assert_not_equals, parameters, - 'Template may contain any element, except the html element, ' - + 'the head element, the body element, or the frameset element. ' - +'The template element and contents are added via body.innerHTML'); - </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist b/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist index 9bb1c9b..2e0dc758 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist +++ b/third_party/WebKit/LayoutTests/external/wpt/lint.whitelist
@@ -236,7 +236,6 @@ GENERATE_TESTS: domxpath/001.html GENERATE_TESTS: domxpath/002.html GENERATE_TESTS: html/semantics/scripting-1/the-template-element/template-element/template-as-a-descendant.html -GENERATE_TESTS: html/semantics/scripting-1/the-template-element/template-element/template-content.html GENERATE_TESTS: html/syntax/parsing/Document.getElementsByTagName-foreign-01.html GENERATE_TESTS: html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-body-context.html GENERATE_TESTS: html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-context.html
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor.https-expected.txt index b7a0ce3d..4973f36 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor.https-expected.txt
@@ -1,28 +1,27 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = 10 duplicate test names: "Test that 'onreading' is called and sensor reading is valid", "sensor reading is correct", "sensor timestamp is updated when time passes", "Test that sensor can be successfully created and its states are correct.", "sensor.start() returns undefined", "no exception is thrown when calling start() on already started sensor", "sensor.stop() returns undefined", "no exception is thrown when calling stop() on already stopped sensor", "throw a 'SecurityError' when constructing sensor object within iframe", "sensor readings can not be fired on the background tab" FAIL Test AbsoluteOrientationSensor.quaternion return a four-element FrozenArray. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code FAIL Test RelativeOrientationSensor.quaternion return a four-element FrozenArray. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code FAIL Test AbsoluteOrientationSensor.populateMatrix() method works correctly. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code FAIL Test RelativeOrientationSensor.populateMatrix() method works correctly. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code -FAIL Test that 'onreading' is called and sensor reading is valid assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code -FAIL sensor reading is correct assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code -FAIL sensor timestamp is updated when time passes assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code -FAIL Test that sensor can be successfully created and its states are correct. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code -PASS sensor.start() returns undefined -PASS no exception is thrown when calling start() on already started sensor -PASS sensor.stop() returns undefined -PASS no exception is thrown when calling stop() on already stopped sensor -PASS throw a 'SecurityError' when constructing sensor object within iframe -FAIL sensor readings can not be fired on the background tab assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code -FAIL Test that 'onreading' is called and sensor reading is valid assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code -FAIL sensor reading is correct assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code -FAIL sensor timestamp is updated when time passes assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code -FAIL Test that sensor can be successfully created and its states are correct. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code -PASS sensor.start() returns undefined -PASS no exception is thrown when calling start() on already started sensor -PASS sensor.stop() returns undefined -PASS no exception is thrown when calling stop() on already stopped sensor -PASS throw a 'SecurityError' when constructing sensor object within iframe -FAIL sensor readings can not be fired on the background tab assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL AbsoluteOrientationSensor: Test that 'onreading' is called and sensor reading is valid assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL AbsoluteOrientationSensor: sensor reading is correct assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL AbsoluteOrientationSensor: sensor timestamp is updated when time passes assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL AbsoluteOrientationSensor: Test that sensor can be successfully created and its states are correct. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +PASS AbsoluteOrientationSensor: sensor.start() returns undefined +PASS AbsoluteOrientationSensor: no exception is thrown when calling start() on already started sensor +PASS AbsoluteOrientationSensor: sensor.stop() returns undefined +PASS AbsoluteOrientationSensor: no exception is thrown when calling stop() on already stopped sensor +PASS AbsoluteOrientationSensor: throw a 'SecurityError' when constructing sensor object within iframe +FAIL AbsoluteOrientationSensor: sensor readings can not be fired on the background tab assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL RelativeOrientationSensor: Test that 'onreading' is called and sensor reading is valid assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL RelativeOrientationSensor: sensor reading is correct assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL RelativeOrientationSensor: sensor timestamp is updated when time passes assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +FAIL RelativeOrientationSensor: Test that sensor can be successfully created and its states are correct. assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code +PASS RelativeOrientationSensor: sensor.start() returns undefined +PASS RelativeOrientationSensor: no exception is thrown when calling start() on already started sensor +PASS RelativeOrientationSensor: sensor.stop() returns undefined +PASS RelativeOrientationSensor: no exception is thrown when calling stop() on already stopped sensor +PASS RelativeOrientationSensor: throw a 'SecurityError' when constructing sensor object within iframe +FAIL RelativeOrientationSensor: sensor readings can not be fired on the background tab assert_unreached: NotReadableError: Could not connect to a sensor Reached unreachable code Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor_insecure_context-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor_insecure_context-expected.txt deleted file mode 100644 index c45af90..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor_insecure_context-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = 1 duplicate test name: "throw a 'SecurityError' when construct sensor in an insecure context" -PASS throw a 'SecurityError' when construct sensor in an insecure context -PASS throw a 'SecurityError' when construct sensor in an insecure context -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor_onerror-manual.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor_onerror-manual.https-expected.txt deleted file mode 100644 index 914d69ab..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/OrientationSensor_onerror-manual.https-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = 1 duplicate test name: "'onerror' event is fired when sensor is not supported" -PASS 'onerror' event is fired when sensor is not supported -PASS 'onerror' event is fired when sensor is not supported -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/http/tests/preload/reuse_sri.html b/third_party/WebKit/LayoutTests/http/tests/preload/reuse_sri.html new file mode 100644 index 0000000..8b824988 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/preload/reuse_sri.html
@@ -0,0 +1,18 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script> +success = function() {} +var t = async_test('Ensure that elements with SRI reuse their preload'); +window.addEventListener('load', t.step_func(function() { + var seen = {}; + performance.getEntriesByType("resource").forEach(function(element) { + var name = element.name; + assert_false(!!seen[name], name + " was loaded more than once"); + seen[name] = true; + }); + t.done(); +})); +</script> +<link rel="stylesheet" href="../security/subresourceIntegrity/style-2-of-3.css" integrity="sha384-j1bGpDxu0bZAb4jBJzciDWuVUuOTXlLvB9WNKDh7Gik9ygF6CctjgYISUwShHmFM"></link> +<script src="../security/subresourceIntegrity/call-success.js" integrity="sha256-B0/62fJSJFrdjEFR9ba04m/D+LHQ+zG6PGcaR0Trpxg="></script>
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-filter-test-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-filter-test-expected.txt index 103ad79..e01f7184 100644 --- a/third_party/WebKit/LayoutTests/inspector/console/console-filter-test-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/console/console-filter-test-expected.txt
@@ -32,7 +32,9 @@ CONSOLE MESSAGE: line 3: 29innerGroup CONSOLE MESSAGE: line 36: console.groupEnd CONSOLE MESSAGE: line 37: console.groupEnd -CONSOLE MESSAGE: line 39: end +CONSOLE MESSAGE: line 41: Hello 1 +CONSOLE MESSAGE: line 42: Hello 2 +CONSOLE MESSAGE: line 44: end Tests that console can filter messages by source. @@ -70,7 +72,9 @@ log-source.js:3 27innerGroup console-filter-test.html:9 28innerGroup log-source.js:3 29innerGroup -console-filter-test.html:39 end +console-filter-test.html:41 Hello 1 +console-filter-test.html:42 Hello 2 +console-filter-test.html:44 end Running: addURL1Filter log-source.js:3 1topGroup @@ -113,7 +117,9 @@ console-filter-test.html:9 24innerGroup console-filter-test.html:9 26innerGroup console-filter-test.html:9 28innerGroup -console-filter-test.html:39 end +console-filter-test.html:41 Hello 1 +console-filter-test.html:42 Hello 2 +console-filter-test.html:44 end Running: restoreURL1Filter >console-filter-test.html:22 outerGroup @@ -152,7 +158,51 @@ log-source.js:3 27innerGroup console-filter-test.html:9 28innerGroup log-source.js:3 29innerGroup -console-filter-test.html:39 end +console-filter-test.html:41 Hello 1 +console-filter-test.html:42 Hello 2 +console-filter-test.html:44 end + +Running: checkContextFilter +>console-filter-test.html:22 outerGroup + >console-filter-test.html:29 innerGroup +console-filter-test.html:41 Hello 1 + +Running: checkAllContextsFilter +console-filter-test.html:9 0topGroup +log-source.js:3 1topGroup +console-filter-test.html:9 2topGroup +log-source.js:3 3topGroup +console-filter-test.html:9 4topGroup +log-source.js:3 5topGroup +console-filter-test.html:9 6topGroup +log-source.js:3 7topGroup +console-filter-test.html:9 8topGroup +log-source.js:3 9topGroup +>console-filter-test.html:22 outerGroup + console-filter-test.html:9 10outerGroup + log-source.js:3 11outerGroup + console-filter-test.html:9 12outerGroup + log-source.js:3 13outerGroup + console-filter-test.html:9 14outerGroup + log-source.js:3 15outerGroup + console-filter-test.html:9 16outerGroup + log-source.js:3 17outerGroup + console-filter-test.html:9 18outerGroup + log-source.js:3 19outerGroup + >console-filter-test.html:29 innerGroup + console-filter-test.html:9 20innerGroup + log-source.js:3 21innerGroup + console-filter-test.html:9 22innerGroup + log-source.js:3 23innerGroup + console-filter-test.html:9 24innerGroup + log-source.js:3 25innerGroup + console-filter-test.html:9 26innerGroup + log-source.js:3 27innerGroup + console-filter-test.html:9 28innerGroup + log-source.js:3 29innerGroup +console-filter-test.html:41 Hello 1 +console-filter-test.html:42 Hello 2 +console-filter-test.html:44 end Running: checkTextFilter >console-filter-test.html:22 outerGroup @@ -201,5 +251,7 @@ log-source.js:3 27innerGroup console-filter-test.html:9 28innerGroup log-source.js:3 29innerGroup -console-filter-test.html:39 end +console-filter-test.html:41 Hello 1 +console-filter-test.html:42 Hello 2 +console-filter-test.html:44 end
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-filter-test.html b/third_party/WebKit/LayoutTests/inspector/console/console-filter-test.html index ab8389a..b93594f 100644 --- a/third_party/WebKit/LayoutTests/inspector/console/console-filter-test.html +++ b/third_party/WebKit/LayoutTests/inspector/console/console-filter-test.html
@@ -36,6 +36,11 @@ console.groupEnd(); console.groupEnd(); + var logger1 = console.context("context1"); + var logger2 = console.context("context2"); + logger1.log("Hello 1"); + logger2.log("Hello 2"); + console.log("end"); runTest(); @@ -98,6 +103,18 @@ dumpVisibleMessages(); next(); }, + function checkContextFilter(next) + { + Console.ConsoleView.instance()._filter.setContext("context1"); + dumpVisibleMessages(); + next(); + }, + function checkAllContextsFilter(next) + { + Console.ConsoleView.instance()._filter.setContext(Console.ConsoleSidebar.AllContextsFilter); + dumpVisibleMessages(); + next(); + }, function checkTextFilter(next) { Console.ConsoleView.instance()._filter._textFilterUI.setValue("outer");
diff --git a/third_party/WebKit/LayoutTests/resources/testharnessreport.js b/third_party/WebKit/LayoutTests/resources/testharnessreport.js index 0d670f8..d2a981f 100644 --- a/third_party/WebKit/LayoutTests/resources/testharnessreport.js +++ b/third_party/WebKit/LayoutTests/resources/testharnessreport.js
@@ -8,15 +8,18 @@ * harness_status)). * * For more documentation about the callback functions and the - * parameters they are called with, see testharness.js. + * parameters they are called with, see testharness.js, or the docs at: + * http://web-platform-tests.org/writing-tests/testharness-api.html */ (function() { - let output_document = document; + let outputDocument = document; + let didDispatchLoadEvent = false; + let localPathRegExp = undefined; // Setup for Blink JavaScript tests. self.testRunner is expected to be - // present when tests are run + // present when tests are run. if (self.testRunner) { testRunner.dumpAsText(); testRunner.waitUntilDone(); @@ -33,30 +36,6 @@ } } - // Disable the default output of testharness.js. The default output formats - // test results into an HTML table. When that table is dumped as text, no - // spacing between cells is preserved, and it is therefore not readable. By - // setting output to false, the HTML table will not be created. - // Also, disable timeout (except for explicit timeout), since the Blink - // layout test runner has its own timeout mechanism. - // See: http://web-platform-tests.org/writing-tests/testharness-api.html - setup({'output': false, 'explicit_timeout': true}); - - /** Converts the testharness test status into the corresponding string. */ - function convertResult(resultStatus) { - switch (resultStatus) { - case 0: - return 'PASS'; - case 1: - return 'FAIL'; - case 2: - return 'TIMEOUT'; - default: - return 'NOTRUN'; - } - } - - let localPathRegExp; if (document.URL.startsWith('file:///')) { const index = document.URL.indexOf('/external/wpt'); if (index >= 0) { @@ -66,19 +45,26 @@ } } - /** Sanitizes the given text for display in test results. */ - function sanitize(text) { - if (!text) { - return ''; + window.addEventListener('load', loadCallback, {'once': true}); + + setup({ + // The default output formats test results into an HTML table, but for + // the Blink layout test runner, we dump the results as text in the + // completion callback, so we disable the default output. + 'output': false, + // The Blink layout test runner has its own timeout mechanism. + 'explicit_timeout': true + }); + + add_start_callback(startCallback); + add_completion_callback(completionCallback); + + /** Loads an automation script if necessary. */ + function loadCallback() { + didDispatchLoadEvent = true; + if (isWPTManualTest()) { + setTimeout(loadAutomationScript, 0); } - // Escape null characters, otherwise diff will think the file is binary. - text = text.replace(/\0/g, '\\0'); - // Escape carriage returns as they break rietveld's difftools. - text = text.replace(/\r/g, '\\r'); - // Replace machine-dependent path with "...". - if (localPathRegExp) - text = text.replace(localPathRegExp, '...'); - return text; } /** Checks whether the current path is a manual test in WPT. */ @@ -95,23 +81,6 @@ return /\/external\/wpt\/.*-manual(\.https)?\.html$/.test(path); } - /** - * Returns a directory part relative to WPT root and a basename part of the - * current test. e.g. - * Current test: file:///.../LayoutTests/external/wpt/pointerevents/foobar.html - * Output: "/pointerevents/foobar" - */ - function pathAndBaseNameInWPT() { - const path = location.pathname; - let matches; - if (location.hostname == 'web-platform.test') { - matches = path.match(/^(\/.*)\.html$/); - return matches ? matches[1] : null; - } - matches = path.match(/external\/wpt(\/.*)\.html$/); - return matches ? matches[1] : null; - } - /** Loads the WPT automation script for the current test, if applicable. */ function loadAutomationScript() { const pathAndBase = pathAndBaseNameInWPT(); @@ -153,26 +122,25 @@ document.head.appendChild(script); } - // Listen for the load event, and load an automation script if necessary. - let didDispatchLoadEvent = false; - window.addEventListener('load', function() { - didDispatchLoadEvent = true; - if (isWPTManualTest()) { - setTimeout(loadAutomationScript, 0); + /** + * Sets the output document based on the given properties. + * Usually the output document is the current document, but it could be + * a separate document in some cases. + */ + function startCallback(properties) { + if (properties.output_document) { + outputDocument = properties.output_document; } - }, {once: true}); + } - add_start_callback(function(properties) { - if (properties.output_document) - output_document = properties.output_document; - }); - - // Using a callback function, test results will be added to the page in a - // manner that allows dumpAsText to produce readable test results. - add_completion_callback(function(tests, harness_status) { + /** + * Adds results to the page in a manner that allows dumpAsText to produce + * readable test results. + */ + function completionCallback(tests, harness_status) { // Create element to hold results. - const resultsElement = output_document.createElement('pre'); + const resultsElement = outputDocument.createElement('pre'); // Declare result string. let resultStr = 'This is a testharness.js-based test.\n'; @@ -180,63 +148,25 @@ // Check harness_status. If it is not 0, tests did not execute // correctly, output the error code and message. if (harness_status.status != 0) { - resultStr += - 'Harness Error. harness_status.status = ' + harness_status.status + - ' , harness_status.message = ' + harness_status.message + '\n'; + resultStr += `Harness Error. ` + + `harness_status.status = ${harness_status.status} , ` + + `harness_status.message = ${harness_status.message}\n`; } - // Iterate through the `tests` array and build a string that contains - // results for all the subtests in this test. - let testResults = ''; - let resultCounter = [0, 0, 0, 0]; - // The reflection tests contain huge number of tests, and Chromium code - // review tool has the 1MB diff size limit. We merge PASS lines. - if (output_document.URL.indexOf('/html/dom/reflection') >= 0) { - for (let i = 0; i < tests.length; ++i) { - if (tests[i].status == 0) { - const colon = tests[i].name.indexOf(':'); - if (colon > 0) { - const prefix = tests[i].name.substring(0, colon + 1); - let j = i + 1; - for (; j < tests.length; ++j) { - if (!tests[j].name.startsWith(prefix) || - tests[j].status != 0) - break; - } - const numPasses = j - i; - if (numPasses > 1) { - resultCounter[0] += numPasses; - testResults += convertResult(tests[i].status) + - ` ${sanitize(prefix)} ${numPasses} tests\n`; - i = j - 1; - continue; - } - } - } - resultCounter[tests[i].status]++; - testResults += convertResult(tests[i].status) + ' ' + - sanitize(tests[i].name) + ' ' + sanitize(tests[i].message) + - '\n'; - } - } else { - for (let i = 0; i < tests.length; ++i) { - resultCounter[tests[i].status]++; - testResults += convertResult(tests[i].status) + ' ' + - sanitize(tests[i].name) + ' ' + sanitize(tests[i].message) + - '\n'; - } - } - if (output_document.URL.indexOf('http://web-platform.test') >= 0 && + // Output failure metrics if there are many. + resultCounts = countResultTypes(tests); + if (outputDocument.URL.indexOf('http://web-platform.test') >= 0 && tests.length >= 50 && - (resultCounter[1] || resultCounter[2] || resultCounter[3])) { - // Output failure metrics if there are many. - resultStr += `Found ${tests.length} tests;` + - ` ${resultCounter[0]} PASS,` + - ` ${resultCounter[1]} FAIL,` + - ` ${resultCounter[2]} TIMEOUT,` + - ` ${resultCounter[3]} NOTRUN.\n`; + (resultCounts[1] || resultCounts[2] || resultCounts[3])) { + + resultStr += failureMetricSummary(resultCounts); } - resultStr += testResults; + + if (outputDocument.URL.indexOf('/html/dom/reflection') >= 0) { + resultStr += compactTestOutput(tests); + } else { + resultStr += testOutput(tests); + } resultStr += 'Harness: the test ran to completion.\n'; @@ -245,12 +175,12 @@ function done() { const xhtmlNS = 'http://www.w3.org/1999/xhtml'; let body = null; - if (output_document.body && output_document.body.tagName == 'BODY' && - output_document.body.namespaceURI == xhtmlNS) { - body = output_document.body; + if (outputDocument.body && outputDocument.body.tagName == 'BODY' && + outputDocument.body.namespaceURI == xhtmlNS) { + body = outputDocument.body; } // A temporary workaround since |window.self| property lookup starts - // failing if the frame is detached. |output_document| may be an + // failing if the frame is detached. |outputDocument| may be an // ancestor of |self| so clearing |textContent| may detach |self|. // To get around this, cache window.self now and use the cached // value. @@ -263,33 +193,34 @@ // test. testRunner.setDumpConsoleMessages(false); - // Anything isn't material to the testrunner output, so should + // Anything in the body isn't part of the output and so should // be hidden from the text dump. if (body) { body.textContent = ''; } } - // Add results element to output_document. + // Add the results element to the output document. if (!body) { - // output_document might be an SVG document. - if (output_document.documentElement) - output_document.documentElement.remove(); - let html = output_document.createElementNS(xhtmlNS, 'html'); - output_document.appendChild(html); - body = output_document.createElementNS(xhtmlNS, 'body'); + // |outputDocument| might be an SVG document. + if (outputDocument.documentElement) { + outputDocument.documentElement.remove(); + } + let html = outputDocument.createElementNS(xhtmlNS, 'html'); + outputDocument.appendChild(html); + body = outputDocument.createElementNS(xhtmlNS, 'body'); body.setAttribute('style', 'white-space:pre;'); html.appendChild(body); } - output_document.body.appendChild(resultsElement); + outputDocument.body.appendChild(resultsElement); if (cachedSelf.testRunner) { testRunner.notifyDone(); } } - if (didDispatchLoadEvent || output_document.readyState != 'loading') { - // This function might not be the last "completion callback", and + if (didDispatchLoadEvent || outputDocument.readyState != 'loading') { + // This function might not be the last completion callback, and // another completion callback might generate more results. // So, we don't dump the results immediately. setTimeout(done, 0); @@ -297,5 +228,120 @@ // Parsing the test HTML isn't finished yet. window.addEventListener('load', done); } - }); + } + + /** + * Returns a directory part relative to WPT root and a basename part of the + * current test. e.g. + * Current test: file:///.../LayoutTests/external/wpt/pointerevents/foobar.html + * Output: "/pointerevents/foobar" + */ + function pathAndBaseNameInWPT() { + const path = location.pathname; + let matches; + if (location.hostname == 'web-platform.test') { + matches = path.match(/^(\/.*)\.html$/); + return matches ? matches[1] : null; + } + matches = path.match(/external\/wpt(\/.*)\.html$/); + return matches ? matches[1] : null; + } + + /** Converts the testharness test status into the corresponding string. */ + function convertResult(resultStatus) { + switch (resultStatus) { + case 0: + return 'PASS'; + case 1: + return 'FAIL'; + case 2: + return 'TIMEOUT'; + default: + return 'NOTRUN'; + } + } + + /** + * Returns a compact output for reflection test results. + * + * The reflection tests contain huge number of tests, and Rietveld + * code review tool had a 1MB diff size limit. We merge PASS lines. + * TODO(qyearsley): Remove this now that we don't use Rietveld. + */ + function compactTestOutput(tests) { + let testResults = []; + for (let i = 0; i < tests.length; ++i) { + if (tests[i].status == 0) { + const colon = tests[i].name.indexOf(':'); + if (colon > 0) { + const prefix = tests[i].name.substring(0, colon + 1); + let j = i + 1; + for (; j < tests.length; ++j) { + if (!tests[j].name.startsWith(prefix) || + tests[j].status != 0) + break; + } + const numPasses = j - i; + if (numPasses > 1) { + testResults.push( + `${convertResult(tests[i].status)} ` + + `${sanitize(prefix)} ${numPasses} tests\n`); + i = j - 1; + continue; + } + } + } + testResults.push( + `${convertResult(tests[i].status)} ` + + `${sanitize(tests[i].name)} ${sanitize(tests[i].message)}\n`); + } + return testResults.join(''); + } + + function testOutput(tests) { + let testResults = ''; + window.tests = tests; + for (let test of tests) { + testResults += `${convertResult(test.status)} ` + + `${sanitize(test.name)} ${sanitize(test.message)}\n`; + } + return testResults; + } + + /** Prepares the given text for display in test results. */ + function sanitize(text) { + if (!text) { + return ''; + } + // Escape null characters, otherwise diff will think the file is binary. + text = text.replace(/\0/g, '\\0'); + // Escape carriage returns as they break rietveld's difftools. + // TODO(qyearsley): Remove this; we are no longer using Rietveld, + // so escaping carriage returns should now be unnecessary. + text = text.replace(/\r/g, '\\r'); + // Replace machine-dependent path with "...". + + if (localPathRegExp) { + text = text.replace(localPathRegExp, '...'); + } + return text; + } + + function countResultTypes(tests) { + const resultCounts = [0, 0, 0, 0]; + for (let test of tests) { + resultCounts[test.status]++; + } + return resultCounts; + } + + function failureMetricSummary(resultCounts) { + const total = resultCounts[0] + resultCounts[1] + resultCounts[2] + resultCounts[3]; + return `Found ${total} tests;` + + ` ${resultCounts[0]} PASS,` + + ` ${resultCounts[1]} FAIL,` + + ` ${resultCounts[2]} TIMEOUT,` + + ` ${resultCounts[3]} NOTRUN.\n`; + } + })();
diff --git a/third_party/WebKit/LayoutTests/vr/getFrameData_windowRAF.html b/third_party/WebKit/LayoutTests/vr/getFrameData_windowRAF.html new file mode 100644 index 0000000..de118fc --- /dev/null +++ b/third_party/WebKit/LayoutTests/vr/getFrameData_windowRAF.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="resources/fake-vr-displays.js"></script> +<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> +<script src="file:///gen/device/vr/vr_service.mojom.js"></script> +<script src="resources/mock-vr-service.js"></script> +<script src="resources/test-constants.js"></script> +<script> +let fakeDisplays = fakeVRDisplays(); + +vr_test( (t, mock_service) => { + return navigator.getVRDisplays().then( (displays) => { + var display = displays[0]; + var expected_pose = VALID_POSE; + var fd = new VRFrameData(); + var counter = 0; + + function onFrame() { + window.requestAnimationFrame(onFrame); + if (counter == 0) { + t.step( () => { + assert_false(display.getFrameData(fd)); + }, "Expecting to not get framedata since there is no pose"); + mock_service.mockVRDisplays_[0].setPose(expected_pose); + t.step( () => { + assert_false(display.getFrameData(fd)); + }, "Does not update within the same frame"); + } else { + t.step( () => { + assert_false(display.getFrameData(fd)); + }, "getFrameData is expected to return false when not in a display RAF callback"); + t.done(); + } + counter++; + } + + window.requestAnimationFrame(onFrame); + }, (err) => { + t.step( () => { + assert_unreached("getVRDisplays rejected"); + }); + }); +}, [fakeDisplays["Pixel"]], +"getFrameData updates on the next frame"); + +</script>
diff --git a/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.h b/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.h index 6d0006b..b1e7761e 100644 --- a/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.h +++ b/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.h
@@ -50,7 +50,7 @@ // As exceptions must always be created in the current realm, reject // promises must also be created in the current realm while regular promises // are created in the relevant realm of the context object. - ScriptState* script_state = ScriptState::ForFunctionObject(info_); + ScriptState* script_state = ScriptState::ForCurrentRealm(info_); V8SetReturnValue(info_, exception_state_.Reject(script_state).V8Value()); }
diff --git a/third_party/WebKit/Source/bindings/modules/v8/custom/V8IDBObserverCustom.cpp b/third_party/WebKit/Source/bindings/modules/v8/custom/V8IDBObserverCustom.cpp index e97218ec..44a60c4 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/custom/V8IDBObserverCustom.cpp +++ b/third_party/WebKit/Source/bindings/modules/v8/custom/V8IDBObserverCustom.cpp
@@ -42,7 +42,7 @@ if (exception_state.HadException()) return; - ScriptState* script_state = ScriptState::ForReceiverObject(info); + ScriptState* script_state = ScriptState::ForRelevantRealm(info); v8::Local<v8::Function> v8_callback = v8::Local<v8::Function>::Cast(info[0]); IDBObserverCallback* callback = IDBObserverCallback::Create(script_state, v8_callback);
diff --git a/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp b/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp index 318f003..4b2f4391 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp +++ b/third_party/WebKit/Source/bindings/modules/v8/wasm/WasmResponseExtensions.cpp
@@ -127,7 +127,7 @@ "WebAssembly", "compile"); ExceptionToRejectPromiseScope reject_promise_scope(args, exception_state); - ScriptState* script_state = ScriptState::ForReceiverObject(args); + ScriptState* script_state = ScriptState::ForRelevantRealm(args); if (!ExecutionContext::From(script_state)) { V8SetReturnValue(args, ScriptPromise().V8Value()); return; @@ -187,7 +187,7 @@ // See https://crbug.com/708238 for tracking avoiding the hand-generated code. void WasmCompileStreamingImpl(const v8::FunctionCallbackInfo<v8::Value>& args) { v8::Isolate* isolate = args.GetIsolate(); - ScriptState* script_state = ScriptState::ForReceiverObject(args); + ScriptState* script_state = ScriptState::ForRelevantRealm(args); v8::Local<v8::Function> compile_callback = v8::Function::New(isolate, CompileFromResponseCallback);
diff --git a/third_party/WebKit/Source/bindings/scripts/generate_conditional_features.py b/third_party/WebKit/Source/bindings/scripts/generate_conditional_features.py index 8d6c5ed..45e1907 100755 --- a/third_party/WebKit/Source/bindings/scripts/generate_conditional_features.py +++ b/third_party/WebKit/Source/bindings/scripts/generate_conditional_features.py
@@ -63,14 +63,16 @@ if 'OriginTrialEnabled' in attribute.extended_attributes: feature_names.add( attribute.extended_attributes['OriginTrialEnabled']) - return list(feature_names) + return feature_names def read_idl_file(reader, idl_filename): - interfaces = reader.read_idl_file(idl_filename).interfaces + definitions = reader.read_idl_file(idl_filename) + interfaces = definitions.interfaces + implements = definitions.implements # There should only be a single interface defined in an IDL file. Return it. assert len(interfaces) == 1 - return interfaces.values()[0] + return (interfaces.values()[0], implements) def interface_is_global(interface): @@ -93,8 +95,19 @@ includes = set() for idl_filename in idl_filenames: - interface = read_idl_file(reader, idl_filename) + interface, implements = read_idl_file(reader, idl_filename) feature_names = get_conditional_feature_names_from_interface(interface) + + # If this interface implements another one, + # it inherits any conditional features from it. + for implement in implements: + assert implement.left_interface == interface.name + implemented_interface, _ = read_idl_file( + reader, + info_provider.interfaces_info[implement.right_interface].get('full_path')) + feature_names |= get_conditional_feature_names_from_interface(implemented_interface) + + feature_names = list(feature_names) if feature_names: is_global = interface_is_global(interface) if interface.is_partial: @@ -102,7 +115,7 @@ # includes if the parent interface is in a different # component. parent_interface_info = info_provider.interfaces_info[interface.name] - parent_interface = read_idl_file( + parent_interface, _ = read_idl_file( reader, parent_interface_info.get('full_path')) is_global = is_global or interface_is_global(parent_interface) parent_component = idl_filename_to_component(
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_attributes.py b/third_party/WebKit/Source/bindings/scripts/v8_attributes.py index b9712f0..d692b85 100644 --- a/third_party/WebKit/Source/bindings/scripts/v8_attributes.py +++ b/third_party/WebKit/Source/bindings/scripts/v8_attributes.py
@@ -486,11 +486,11 @@ includes.add('bindings/core/v8/V8ErrorHandler.h') arguments.append( 'V8EventListenerHelper::EnsureErrorHandler(' + - 'ScriptState::ForReceiverObject(info), v8Value)') + 'ScriptState::ForRelevantRealm(info), v8Value)') else: arguments.append( 'V8EventListenerHelper::GetEventListener(' + - 'ScriptState::ForReceiverObject(info), v8Value, true, ' + + 'ScriptState::ForRelevantRealm(info), v8Value, true, ' + 'kListenerFindOrCreate)') else: arguments.append('cppValue')
diff --git a/third_party/WebKit/Source/bindings/templates/attributes.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/attributes.cpp.tmpl index d260370f..d5e358b 100644 --- a/third_party/WebKit/Source/bindings/templates/attributes.cpp.tmpl +++ b/third_party/WebKit/Source/bindings/templates/attributes.cpp.tmpl
@@ -108,9 +108,9 @@ {% if attribute.is_call_with_script_state %} {% if attribute.is_static %} - ScriptState* scriptState = ScriptState::ForFunctionObject(info); + ScriptState* scriptState = ScriptState::ForCurrentRealm(info); {% else %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); {% endif %} {% endif %} @@ -235,9 +235,9 @@ {% if world_suffix in attribute.activity_logging_world_list_for_getter %} {% if attribute.is_static %} - ScriptState* scriptState = ScriptState::ForFunctionObject(info); + ScriptState* scriptState = ScriptState::ForCurrentRealm(info); {% else %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); {% endif %} V8PerContextData* contextData = scriptState->PerContextData(); if ( @@ -410,9 +410,9 @@ {% if attribute.is_call_with_script_state %} {% if attribute.is_static %} - ScriptState* scriptState = ScriptState::ForFunctionObject(info); + ScriptState* scriptState = ScriptState::ForCurrentRealm(info); {% else %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); {% endif %} {% endif %} @@ -461,9 +461,9 @@ {% if world_suffix in attribute.activity_logging_world_list_for_setter %} {% if attribute.is_static %} - ScriptState* scriptState = ScriptState::ForFunctionObject(info); + ScriptState* scriptState = ScriptState::ForCurrentRealm(info); {% else %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); {% endif %} V8PerContextData* contextData = scriptState->PerContextData(); if (
diff --git a/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl index 0e82bccd..0836f93d 100644 --- a/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl +++ b/third_party/WebKit/Source/bindings/templates/interface.cpp.tmpl
@@ -21,7 +21,7 @@ {% set getter_name = getter.name or 'AnonymousIndexedGetter' %} {% set getter_arguments = ['index'] %} {% if getter.is_call_with_script_state %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); {% set getter_arguments = ['scriptState'] + getter_arguments %} {% endif %} {% if getter.is_raises_exception %} @@ -89,7 +89,7 @@ {% set setter_name = setter.name or 'AnonymousIndexedSetter' %} {% set setter_arguments = ['index', 'propertyValue'] %} {% if setter.is_call_with_script_state %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); {% set setter_arguments = ['scriptState'] + setter_arguments %} {% endif %} {% if setter.is_raises_exception %} @@ -210,7 +210,7 @@ {% set deleter_name = deleter.name or 'AnonymousIndexedDeleter' %} {% set deleter_arguments = ['index'] %} {% if deleter.is_call_with_script_state %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); {% set deleter_arguments = ['scriptState'] + deleter_arguments %} {% endif %} {% if deleter.is_raises_exception %} @@ -321,7 +321,7 @@ ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kGetterContext, "{{interface_name}}", nameInUtf8.data()); {% endif %} {% if getter.is_call_with_script_state %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); {% endif %} {{cpp_class}}* impl = {{v8_class}}::toImpl(info.Holder()); @@ -371,7 +371,7 @@ ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kSetterContext, "{{interface_name}}", nameInUtf8.data()); {% endif %} {% if setter.is_call_with_script_state %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); {% endif %} {{cpp_class}}* impl = {{v8_class}}::toImpl(info.Holder()); @@ -441,7 +441,7 @@ ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kDeletionContext, "{{interface_name}}", nameInUtf8.data()); {% endif %} {% if deleter.is_call_with_script_state %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); {% endif %} {{cpp_class}}* impl = {{v8_class}}::toImpl(info.Holder()); @@ -503,7 +503,7 @@ const CString& nameInUtf8 = name.Utf8(); ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kGetterContext, "{{interface_name}}", nameInUtf8.data()); {% if getter.is_call_with_script_state %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); {% endif %} {{cpp_class}}* impl = {{v8_class}}::toImpl(info.Holder());
diff --git a/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl index 0aae2e86..4c693bb 100644 --- a/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl +++ b/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl
@@ -57,9 +57,9 @@ {% if 'scriptState' in function_call %} {% if method.is_static %} - ScriptState* scriptState = ScriptState::ForFunctionObject(info); + ScriptState* scriptState = ScriptState::ForCurrentRealm(info); {% else %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); {% endif %} {% endif %} @@ -504,9 +504,9 @@ {% endif %}{# not method.overloads #} {% if world_suffix in method.activity_logging_world_list %} {% if method.is_static %} - ScriptState* scriptState = ScriptState::ForFunctionObject(info); + ScriptState* scriptState = ScriptState::ForCurrentRealm(info); {% else %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); {% endif %} V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { @@ -594,7 +594,8 @@ ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kConstructionContext, "{{interface_name}}"); {% endif %} {% if 'scriptState' in function_call %} - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::From( + info.NewTarget().As<v8::Object>()->CreationContext()); {% endif %} {{function_call | indent(2)}}
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp index 2c428d4..7cd9e0be 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
@@ -825,7 +825,7 @@ // Prepare the value to be set. - impl->setImplementsEventHandlerAttribute(V8EventListenerHelper::GetEventListener(ScriptState::ForReceiverObject(info), v8Value, true, kListenerFindOrCreate)); + impl->setImplementsEventHandlerAttribute(V8EventListenerHelper::GetEventListener(ScriptState::ForRelevantRealm(info), v8Value, true, kListenerFindOrCreate)); } static void implementsRuntimeEnabledNodeAttributeAttributeGetter(const v8::FunctionCallbackInfo<v8::Value>& info) { @@ -1989,7 +1989,7 @@ TestInterfaceImplementation* impl = V8TestInterface::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); Iterator* result = impl->keysForBinding(scriptState, exceptionState); if (exceptionState.HadException()) { @@ -2003,7 +2003,7 @@ TestInterfaceImplementation* impl = V8TestInterface::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); Iterator* result = impl->valuesForBinding(scriptState, exceptionState); if (exceptionState.HadException()) { @@ -2017,7 +2017,7 @@ TestInterfaceImplementation* impl = V8TestInterface::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 1)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length())); @@ -2046,7 +2046,7 @@ TestInterfaceImplementation* impl = V8TestInterface::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); ScriptValue result = impl->toJSONForBinding(scriptState, exceptionState); if (exceptionState.HadException()) { @@ -2066,7 +2066,7 @@ TestInterfaceImplementation* impl = V8TestInterface::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); Iterator* result = impl->GetIterator(scriptState, exceptionState); if (exceptionState.HadException()) {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp index 4c6bd4bc..03f47035 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
@@ -256,7 +256,7 @@ TestInterface2* impl = V8TestInterface2::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); Iterator* result = impl->keysForBinding(scriptState, exceptionState); if (exceptionState.HadException()) { @@ -270,7 +270,7 @@ TestInterface2* impl = V8TestInterface2::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); Iterator* result = impl->entriesForBinding(scriptState, exceptionState); if (exceptionState.HadException()) { @@ -284,7 +284,7 @@ TestInterface2* impl = V8TestInterface2::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 1)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length())); @@ -313,7 +313,7 @@ TestInterface2* impl = V8TestInterface2::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 1)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length())); @@ -346,7 +346,7 @@ TestInterface2* impl = V8TestInterface2::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); Iterator* result = impl->GetIterator(scriptState, exceptionState); if (exceptionState.HadException()) {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp index cf20638..e021f5d8 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
@@ -74,7 +74,8 @@ static void constructor1(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kConstructionContext, "TestInterfaceConstructor"); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::From( + info.NewTarget().As<v8::Object>()->CreationContext()); ExecutionContext* executionContext = ToExecutionContext( info.NewTarget().As<v8::Object>()->CreationContext()); @@ -91,7 +92,8 @@ static void constructor2(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kConstructionContext, "TestInterfaceConstructor"); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::From( + info.NewTarget().As<v8::Object>()->CreationContext()); double doubleArg; V8StringResource<> stringArg; @@ -169,7 +171,8 @@ static void constructor3(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kConstructionContext, "TestInterfaceConstructor"); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::From( + info.NewTarget().As<v8::Object>()->CreationContext()); V8StringResource<> arg; V8StringResource<> optArg; @@ -216,7 +219,8 @@ static void constructor4(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kConstructionContext, "TestInterfaceConstructor"); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::From( + info.NewTarget().As<v8::Object>()->CreationContext()); V8StringResource<> arg; V8StringResource<> arg2; @@ -339,7 +343,8 @@ } ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kConstructionContext, "TestInterfaceConstructor"); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::From( + info.NewTarget().As<v8::Object>()->CreationContext()); if (UNLIKELY(info.Length() < 1)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length()));
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp index 38a8ba8..478501ff 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
@@ -133,7 +133,7 @@ TestInterfaceGarbageCollected* impl = V8TestInterfaceGarbageCollected::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); Iterator* result = impl->keysForBinding(scriptState, exceptionState); if (exceptionState.HadException()) { @@ -147,7 +147,7 @@ TestInterfaceGarbageCollected* impl = V8TestInterfaceGarbageCollected::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); Iterator* result = impl->entriesForBinding(scriptState, exceptionState); if (exceptionState.HadException()) { @@ -161,7 +161,7 @@ TestInterfaceGarbageCollected* impl = V8TestInterfaceGarbageCollected::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 1)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length())); @@ -190,7 +190,7 @@ TestInterfaceGarbageCollected* impl = V8TestInterfaceGarbageCollected::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 1)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length())); @@ -214,7 +214,7 @@ TestInterfaceGarbageCollected* impl = V8TestInterfaceGarbageCollected::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 1)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length())); @@ -238,7 +238,7 @@ TestInterfaceGarbageCollected* impl = V8TestInterfaceGarbageCollected::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); impl->clearForBinding(scriptState, exceptionState); if (exceptionState.HadException()) { @@ -251,7 +251,7 @@ TestInterfaceGarbageCollected* impl = V8TestInterfaceGarbageCollected::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 1)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length())); @@ -275,7 +275,7 @@ TestInterfaceGarbageCollected* impl = V8TestInterfaceGarbageCollected::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); Iterator* result = impl->GetIterator(scriptState, exceptionState); if (exceptionState.HadException()) {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp index 7805513..08149d1 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
@@ -149,7 +149,7 @@ // Prepare the value to be set. - impl->setEventHandlerAttribute(V8EventListenerHelper::GetEventListener(ScriptState::ForReceiverObject(info), v8Value, true, kListenerFindOrCreate)); + impl->setEventHandlerAttribute(V8EventListenerHelper::GetEventListener(ScriptState::ForRelevantRealm(info), v8Value, true, kListenerFindOrCreate)); } static void perWorldBindingsReadonlyTestInterfaceEmptyAttributeAttributeGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp index 324e5497..f88287b 100644 --- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp +++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
@@ -1707,7 +1707,7 @@ // Prepare the value to be set. - impl->setEventHandlerAttribute(V8EventListenerHelper::GetEventListener(ScriptState::ForReceiverObject(info), v8Value, true, kListenerFindOrCreate)); + impl->setEventHandlerAttribute(V8EventListenerHelper::GetEventListener(ScriptState::ForRelevantRealm(info), v8Value, true, kListenerFindOrCreate)); } static void doubleOrStringAttributeAttributeGetter(const v8::FunctionCallbackInfo<v8::Value>& info) { @@ -2187,7 +2187,7 @@ TestObject* impl = V8TestObject::toImpl(holder); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8SetReturnValue(info, impl->callWithScriptStateAnyAttribute(scriptState).V8Value()); } @@ -2204,7 +2204,7 @@ // Prepare the value to be set. ScriptValue cppValue = ScriptValue(ScriptState::Current(info.GetIsolate()), v8Value); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); impl->setCallWithScriptStateAnyAttribute(scriptState, cppValue); } @@ -2216,7 +2216,7 @@ ExecutionContext* executionContext = ExecutionContext::ForRelevantRealm(info); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8SetReturnValue(info, impl->callWithExecutionContextAndScriptStateAnyAttribute(scriptState, executionContext).V8Value()); } @@ -2235,7 +2235,7 @@ ExecutionContext* executionContext = ExecutionContext::ForRelevantRealm(info); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); impl->setCallWithExecutionContextAndScriptStateAnyAttribute(scriptState, executionContext, cppValue); } @@ -7867,7 +7867,7 @@ TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 1)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length())); @@ -7888,7 +7888,7 @@ TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 2)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(2, info.Length())); @@ -8049,7 +8049,7 @@ static void callWithScriptStateVoidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) { TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); impl->callWithScriptStateVoidMethod(scriptState); } @@ -8057,7 +8057,7 @@ static void callWithScriptStateLongMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) { TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); int32_t result = impl->callWithScriptStateLongMethod(scriptState); V8SetReturnValueInt(info, result); @@ -8066,7 +8066,7 @@ static void callWithScriptStateExecutionContextVoidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) { TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); ExecutionContext* executionContext = ExecutionContext::ForRelevantRealm(info); impl->callWithScriptStateExecutionContextVoidMethod(scriptState, executionContext); @@ -8075,7 +8075,7 @@ static void callWithScriptStateScriptArgumentsVoidMethodMethod(const v8::FunctionCallbackInfo<v8::Value>& info) { TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); ScriptArguments* scriptArguments(ScriptArguments::Create(scriptState, info, 0)); impl->callWithScriptStateScriptArgumentsVoidMethod(scriptState, scriptArguments); @@ -8086,7 +8086,7 @@ TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); bool optionalBooleanArg; int numArgsPassed = info.Length(); @@ -8123,7 +8123,7 @@ static void callWithThisValueMethod(const v8::FunctionCallbackInfo<v8::Value>& info) { TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); impl->callWithThisValue(ScriptValue(scriptState, info.Holder())); } @@ -9258,7 +9258,7 @@ TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); bool result = impl->myMaplikeClear(scriptState, exceptionState); if (exceptionState.HadException()) { @@ -9272,7 +9272,7 @@ TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); Iterator* result = impl->keysForBinding(scriptState, exceptionState); if (exceptionState.HadException()) { @@ -9286,7 +9286,7 @@ TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); Iterator* result = impl->valuesForBinding(scriptState, exceptionState); if (exceptionState.HadException()) { @@ -9300,7 +9300,7 @@ TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 1)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length())); @@ -9329,7 +9329,7 @@ TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 1)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length())); @@ -9353,7 +9353,7 @@ TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 1)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length())); @@ -9377,7 +9377,7 @@ TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 1)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(1, info.Length())); @@ -9401,7 +9401,7 @@ TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); if (UNLIKELY(info.Length() < 2)) { exceptionState.ThrowTypeError(ExceptionMessages::NotEnoughArguments(2, info.Length())); @@ -9442,7 +9442,7 @@ TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); Iterator* result = impl->GetIterator(scriptState, exceptionState); if (exceptionState.HadException()) { @@ -9452,7 +9452,7 @@ } static void namedPropertyGetter(const AtomicString& name, const v8::PropertyCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); TestObject* impl = V8TestObject::toImpl(info.Holder()); ScriptValue result = impl->AnonymousNamedGetter(scriptState, name); @@ -9462,7 +9462,7 @@ } static void namedPropertySetter(const AtomicString& name, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); TestObject* impl = V8TestObject::toImpl(info.Holder()); V8StringResource<> propertyValue = v8Value; @@ -9476,7 +9476,7 @@ } static void namedPropertyDeleter(const AtomicString& name, const v8::PropertyCallbackInfo<v8::Boolean>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); TestObject* impl = V8TestObject::toImpl(info.Holder()); @@ -9489,7 +9489,7 @@ static void namedPropertyQuery(const AtomicString& name, const v8::PropertyCallbackInfo<v8::Integer>& info) { const CString& nameInUtf8 = name.Utf8(); ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kGetterContext, "TestObject", nameInUtf8.data()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); TestObject* impl = V8TestObject::toImpl(info.Holder()); @@ -9524,7 +9524,7 @@ if (index >= impl->length()) return; // Returns undefined due to out-of-range. - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); ScriptValue result = impl->item(scriptState, index); V8SetReturnValue(info, result.V8Value()); } @@ -9558,7 +9558,7 @@ if (!propertyValue.Prepare()) return; - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); bool result = impl->setItem(scriptState, index, propertyValue); if (!result) return; @@ -9570,7 +9570,7 @@ TestObject* impl = V8TestObject::toImpl(info.Holder()); - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); DeleteResult result = impl->AnonymousIndexedDeleter(scriptState, index, exceptionState); if (exceptionState.HadException()) return; @@ -10218,7 +10218,7 @@ } void V8TestObject::activityLoggingAccessForAllWorldsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { contextData->ActivityLogger()->LogGetter("TestObject.activityLoggingAccessForAllWorldsLongAttribute"); @@ -10230,7 +10230,7 @@ void V8TestObject::activityLoggingAccessForAllWorldsLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Local<v8::Value> v8Value = info[0]; - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { contextData->ActivityLogger()->LogSetter("TestObject.activityLoggingAccessForAllWorldsLongAttribute", v8Value); @@ -10240,7 +10240,7 @@ } void V8TestObject::activityLoggingGetterForAllWorldsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { contextData->ActivityLogger()->LogGetter("TestObject.activityLoggingGetterForAllWorldsLongAttribute"); @@ -10262,7 +10262,7 @@ void V8TestObject::activityLoggingSetterForAllWorldsLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Local<v8::Value> v8Value = info[0]; - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { contextData->ActivityLogger()->LogSetter("TestObject.activityLoggingSetterForAllWorldsLongAttribute", v8Value); @@ -10488,7 +10488,7 @@ } void V8TestObject::activityLoggingAccessPerWorldBindingsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { contextData->ActivityLogger()->LogGetter("TestObject.activityLoggingAccessPerWorldBindingsLongAttribute"); @@ -10500,7 +10500,7 @@ void V8TestObject::activityLoggingAccessPerWorldBindingsLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Local<v8::Value> v8Value = info[0]; - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { contextData->ActivityLogger()->LogSetter("TestObject.activityLoggingAccessPerWorldBindingsLongAttribute", v8Value); @@ -10510,7 +10510,7 @@ } void V8TestObject::activityLoggingAccessPerWorldBindingsLongAttributeAttributeGetterCallbackForMainWorld(const v8::FunctionCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { contextData->ActivityLogger()->LogGetter("TestObject.activityLoggingAccessPerWorldBindingsLongAttribute"); @@ -10522,7 +10522,7 @@ void V8TestObject::activityLoggingAccessPerWorldBindingsLongAttributeAttributeSetterCallbackForMainWorld(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Local<v8::Value> v8Value = info[0]; - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { contextData->ActivityLogger()->LogSetter("TestObject.activityLoggingAccessPerWorldBindingsLongAttribute", v8Value); @@ -10532,7 +10532,7 @@ } void V8TestObject::activityLoggingAccessForIsolatedWorldsPerWorldBindingsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { contextData->ActivityLogger()->LogGetter("TestObject.activityLoggingAccessForIsolatedWorldsPerWorldBindingsLongAttribute"); @@ -10544,7 +10544,7 @@ void V8TestObject::activityLoggingAccessForIsolatedWorldsPerWorldBindingsLongAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Local<v8::Value> v8Value = info[0]; - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { contextData->ActivityLogger()->LogSetter("TestObject.activityLoggingAccessForIsolatedWorldsPerWorldBindingsLongAttribute", v8Value); @@ -10564,7 +10564,7 @@ } void V8TestObject::activityLoggingGetterPerWorldBindingsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { contextData->ActivityLogger()->LogGetter("TestObject.activityLoggingGetterPerWorldBindingsLongAttribute"); @@ -10580,7 +10580,7 @@ } void V8TestObject::activityLoggingGetterPerWorldBindingsLongAttributeAttributeGetterCallbackForMainWorld(const v8::FunctionCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { contextData->ActivityLogger()->LogGetter("TestObject.activityLoggingGetterPerWorldBindingsLongAttribute"); @@ -10596,7 +10596,7 @@ } void V8TestObject::activityLoggingGetterForIsolatedWorldsPerWorldBindingsLongAttributeAttributeGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { contextData->ActivityLogger()->LogGetter("TestObject.activityLoggingGetterForIsolatedWorldsPerWorldBindingsLongAttribute"); @@ -11919,7 +11919,7 @@ } void V8TestObject::activityLoggingAccessForAllWorldsMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kExecutionContext, "TestObject", "activityLoggingAccessForAllWorldsMethod"); @@ -12069,7 +12069,7 @@ } void V8TestObject::activityLoggingForAllWorldsPerWorldBindingsVoidMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kExecutionContext, "TestObject", "activityLoggingForAllWorldsPerWorldBindingsVoidMethod"); @@ -12080,7 +12080,7 @@ } void V8TestObject::activityLoggingForAllWorldsPerWorldBindingsVoidMethodMethodCallbackForMainWorld(const v8::FunctionCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kExecutionContext, "TestObject", "activityLoggingForAllWorldsPerWorldBindingsVoidMethod"); @@ -12091,7 +12091,7 @@ } void V8TestObject::activityLoggingForIsolatedWorldsPerWorldBindingsVoidMethodMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ScriptState* scriptState = ScriptState::ForReceiverObject(info); + ScriptState* scriptState = ScriptState::ForRelevantRealm(info); V8PerContextData* contextData = scriptState->PerContextData(); if (contextData && contextData->ActivityLogger()) { ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kExecutionContext, "TestObject", "activityLoggingForIsolatedWorldsPerWorldBindingsVoidMethod");
diff --git a/third_party/WebKit/Source/core/DEPS b/third_party/WebKit/Source/core/DEPS index f2a2386..86516a8 100644 --- a/third_party/WebKit/Source/core/DEPS +++ b/third_party/WebKit/Source/core/DEPS
@@ -19,7 +19,6 @@ "!core/exported", # We do not want any new dependencies on Web(Local|Remote)FrameBase.h until # we resolve the control layer. - "!core/frame/WebLocalFrameBase.h", "!core/frame/WebLocalFrameImpl.h", "!core/frame/WebRemoteFrameImpl.h", ]
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp index 3f676ed..c4ffff4 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -304,7 +304,6 @@ } static CSSValue* ConsumePrefixedBackgroundBox(CSSParserTokenRange& range, - const CSSParserContext* context, bool allow_text_value) { // The values 'border', 'padding' and 'content' are deprecated and do not // apply to the version of the property that has the -webkit- prefix removed. @@ -363,12 +362,10 @@ return CSSPropertyBackgroundUtils::ConsumeMaskSourceType(range); case CSSPropertyWebkitBackgroundClip: case CSSPropertyWebkitMaskClip: - return ConsumePrefixedBackgroundBox(range, context, - true /* allow_text_value */); + return ConsumePrefixedBackgroundBox(range, true /* allow_text_value */); case CSSPropertyWebkitBackgroundOrigin: case CSSPropertyWebkitMaskOrigin: - return ConsumePrefixedBackgroundBox(range, context, - false /* allow_text_value */); + return ConsumePrefixedBackgroundBox(range, false /* allow_text_value */); case CSSPropertyBackgroundImage: case CSSPropertyWebkitMaskImage: return ConsumeImageOrNone(range, context); @@ -451,11 +448,11 @@ case CSSPropertyWebkitBackgroundClip: case CSSPropertyWebkitMaskClip: return ConsumeCommaSeparatedList(ConsumePrefixedBackgroundBox, range_, - context_, true /* allow_text_value */); + true /* allow_text_value */); case CSSPropertyWebkitBackgroundOrigin: case CSSPropertyWebkitMaskOrigin: return ConsumeCommaSeparatedList(ConsumePrefixedBackgroundBox, range_, - context_, false /* allow_text_value */); + false /* allow_text_value */); case CSSPropertyWebkitMaskRepeatX: case CSSPropertyWebkitMaskRepeatY: return nullptr;
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index c74e6c88..1f9a43a86 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -197,6 +197,7 @@ #include "core/loader/NavigationScheduler.h" #include "core/loader/PrerendererClient.h" #include "core/loader/appcache/ApplicationCacheHost.h" +#include "core/origin_trials/OriginTrials.h" #include "core/page/ChromeClient.h" #include "core/page/EventWithHitTestResults.h" #include "core/page/FocusController.h" @@ -4801,7 +4802,7 @@ // createEvent for TouchEvent should throw DOM exception if touch event // feature detection is not enabled. See crbug.com/392584#c22 if (DeprecatedEqualIgnoringCase(event_type, "TouchEvent") && - !RuntimeEnabledFeatures::TouchEventFeatureDetectionEnabled()) + !OriginTrials::touchEventFeatureDetectionEnabled(execution_context)) break; return event; }
diff --git a/third_party/WebKit/Source/core/dom/Document.idl b/third_party/WebKit/Source/core/dom/Document.idl index 610c2096..5ed7b84 100644 --- a/third_party/WebKit/Source/core/dom/Document.idl +++ b/third_party/WebKit/Source/core/dom/Document.idl
@@ -158,7 +158,7 @@ // Touch Events // https://w3c.github.io/touch-events/#extensions-to-the-document-interface - [RuntimeEnabled=TouchEventFeatureDetection, Measure, LegacyInterfaceTypeChecking, Custom=CallPrologue] + [OriginTrialEnabled=TouchEventFeatureDetection, Measure, LegacyInterfaceTypeChecking, Custom=CallPrologue] Touch createTouch(Window view, EventTarget target, long identifier, @@ -170,7 +170,7 @@ optional unrestricted double radiusY = 0, optional unrestricted float rotationAngle = 0, optional unrestricted float force = 0); - [RuntimeEnabled=TouchEventFeatureDetection] TouchList createTouchList(Touch... touches); + [OriginTrialEnabled=TouchEventFeatureDetection] TouchList createTouchList(Touch... touches); // Custom Elements // https://w3c.github.io/webcomponents/spec/custom/#extensions-to-document-interface-to-register
diff --git a/third_party/WebKit/Source/core/dom/GlobalEventHandlers.idl b/third_party/WebKit/Source/core/dom/GlobalEventHandlers.idl index 6735073b..49d756b 100644 --- a/third_party/WebKit/Source/core/dom/GlobalEventHandlers.idl +++ b/third_party/WebKit/Source/core/dom/GlobalEventHandlers.idl
@@ -115,8 +115,8 @@ // Touch Events // https://w3c.github.io/touch-events/#extensions-to-the-globaleventhandlers-interface - [RuntimeEnabled=TouchEventFeatureDetection] attribute EventHandler ontouchcancel; - [RuntimeEnabled=TouchEventFeatureDetection] attribute EventHandler ontouchend; - [RuntimeEnabled=TouchEventFeatureDetection] attribute EventHandler ontouchmove; - [RuntimeEnabled=TouchEventFeatureDetection] attribute EventHandler ontouchstart; + [OriginTrialEnabled=TouchEventFeatureDetection] attribute EventHandler ontouchcancel; + [OriginTrialEnabled=TouchEventFeatureDetection] attribute EventHandler ontouchend; + [OriginTrialEnabled=TouchEventFeatureDetection] attribute EventHandler ontouchmove; + [OriginTrialEnabled=TouchEventFeatureDetection] attribute EventHandler ontouchstart; };
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp index e5ed4a88..9af3573 100644 --- a/third_party/WebKit/Source/core/dom/Node.cpp +++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -313,13 +313,13 @@ #if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS) TrackForDebugging(); #endif - InstanceCounters::IncrementNodeCounter(); + InstanceCounters::IncrementCounter(InstanceCounters::kNodeCounter); } Node::~Node() { if (!HasRareData() && !data_.node_layout_data_->IsSharedEmptyData()) delete data_.node_layout_data_; - InstanceCounters::DecrementNodeCounter(); + InstanceCounters::DecrementCounter(InstanceCounters::kNodeCounter); } NodeRareData* Node::RareData() const {
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp index de9b7b1..c0058dc2 100644 --- a/third_party/WebKit/Source/core/editing/SelectionController.cpp +++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp
@@ -226,13 +226,13 @@ static SelectionInFlatTree ExtendSelectionAsNonDirectional( const PositionInFlatTree& position, - const VisibleSelectionInFlatTree& selection, + const SelectionInFlatTree& selection, TextGranularity granularity) { DCHECK(!selection.IsNone()); DCHECK(position.IsNotNull()); // Shift+Click deselects when selection was created right-to-left - const PositionInFlatTree& start = selection.Start(); - const PositionInFlatTree& end = selection.End(); + const PositionInFlatTree& start = selection.ComputeStartPosition(); + const PositionInFlatTree& end = selection.ComputeEndPosition(); if (position < start) { return SelectionInFlatTree::Builder() .SetBaseAndExtent( @@ -334,7 +334,8 @@ frame_->GetEditor().Behavior().ShouldConsiderSelectionAsDirectional() ? ExtendSelectionAsDirectional(pos, selection.AsSelection(), granularity) - : ExtendSelectionAsNonDirectional(pos, selection, granularity), + : ExtendSelectionAsNonDirectional(pos, selection.AsSelection(), + granularity), granularity, HandleVisibility::kNotVisible); return false; }
diff --git a/third_party/WebKit/Source/core/editing/SelectionEditor.cpp b/third_party/WebKit/Source/core/editing/SelectionEditor.cpp index 7d87872..15753c71 100644 --- a/third_party/WebKit/Source/core/editing/SelectionEditor.cpp +++ b/third_party/WebKit/Source/core/editing/SelectionEditor.cpp
@@ -120,6 +120,7 @@ } void SelectionEditor::DidChangeChildren(const ContainerNode&) { + selection_.ResetDirectionCache(); MarkCacheDirty(); DidFinishDOMMutation(); } @@ -132,6 +133,7 @@ } selection_.base_ = new_base; selection_.extent_ = new_extent; + selection_.ResetDirectionCache(); MarkCacheDirty(); DidFinishDOMMutation(); }
diff --git a/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp b/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp index 879ff74b..97e695b6 100644 --- a/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp +++ b/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp
@@ -149,12 +149,32 @@ template <typename Strategy> bool SelectionTemplate<Strategy>::IsBaseFirst() const { DCHECK(AssertValid()); - if (direction_ == Direction::kNotComputed) - direction_ = base_ <= extent_ ? Direction::kForward : Direction::kBackward; + if (base_ == extent_) { + DCHECK_EQ(direction_, Direction::kForward); + return true; + } + if (direction_ == Direction::kForward) { + DCHECK_LE(base_, extent_); + return true; + } + if (direction_ == Direction::kBackward) { + DCHECK_GT(base_, extent_); + return false; + } + // Note: Since same position can be represented in different anchor type, + // e.g. Position(div, 0) and BeforeNode(first-child), we use |<=| to check + // forward selection. + DCHECK_EQ(direction_, Direction::kNotComputed); + direction_ = base_ <= extent_ ? Direction::kForward : Direction::kBackward; return direction_ == Direction::kForward; } template <typename Strategy> +void SelectionTemplate<Strategy>::ResetDirectionCache() const { + direction_ = base_ == extent_ ? Direction::kForward : Direction::kNotComputed; +} + +template <typename Strategy> SelectionType SelectionTemplate<Strategy>::Type() const { if (base_.IsNull()) return kNoSelection; @@ -206,8 +226,7 @@ SelectionTemplate<Strategy> SelectionTemplate<Strategy>::Builder::Build() const { DCHECK(selection_.AssertValid()); - selection_.direction_ = - selection_.IsNone() ? Direction::kForward : Direction::kNotComputed; + selection_.ResetDirectionCache(); return selection_; }
diff --git a/third_party/WebKit/Source/core/editing/SelectionTemplate.h b/third_party/WebKit/Source/core/editing/SelectionTemplate.h index a265a10..b5288c6 100644 --- a/third_party/WebKit/Source/core/editing/SelectionTemplate.h +++ b/third_party/WebKit/Source/core/editing/SelectionTemplate.h
@@ -116,6 +116,7 @@ }; Document* GetDocument() const; + void ResetDirectionCache() const; PositionTemplate<Strategy> base_; PositionTemplate<Strategy> extent_;
diff --git a/third_party/WebKit/Source/core/editing/TextFinder.cpp b/third_party/WebKit/Source/core/editing/TextFinder.cpp index c62b7e4..a796228 100644 --- a/third_party/WebKit/Source/core/editing/TextFinder.cpp +++ b/third_party/WebKit/Source/core/editing/TextFinder.cpp
@@ -41,7 +41,7 @@ #include "core/editing/iterators/SearchBuffer.h" #include "core/editing/markers/DocumentMarker.h" #include "core/editing/markers/DocumentMarkerController.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrameView.h" #include "core/frame/WebLocalFrameImpl.h" #include "core/layout/LayoutObject.h" @@ -241,9 +241,7 @@ // If the user has set the selection since the match was found, we // don't focus anything. - VisibleSelection selection( - GetFrame()->Selection().ComputeVisibleSelectionInDOMTreeDeprecated()); - if (!selection.IsNone()) + if (!GetFrame()->Selection().GetSelectionInDOMTree().IsNone()) return; // Need to clean out style and layout state before querying
diff --git a/third_party/WebKit/Source/core/exported/DEPS b/third_party/WebKit/Source/core/exported/DEPS index 389efef..09e1f4ec 100644 --- a/third_party/WebKit/Source/core/exported/DEPS +++ b/third_party/WebKit/Source/core/exported/DEPS
@@ -3,7 +3,4 @@ # exported. "+core/exported", "+public/web", - # We do not want any new dependencies on Web(Local|Remote)FrameBase.h until - # we resolve the control layer. - "+core/frame/WebLocalFrameBase.h", ]
diff --git a/third_party/WebKit/Source/core/exported/WebDevToolsFrontendImpl.cpp b/third_party/WebKit/Source/core/exported/WebDevToolsFrontendImpl.cpp index 8b25ae5..07f74296 100644 --- a/third_party/WebKit/Source/core/exported/WebDevToolsFrontendImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebDevToolsFrontendImpl.cpp
@@ -33,7 +33,7 @@ #include "bindings/core/v8/ScriptController.h" #include "bindings/core/v8/V8BindingForCore.h" #include "bindings/core/v8/V8DevToolsHost.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrame.h" #include "core/frame/WebLocalFrameImpl.h" #include "core/inspector/DevToolsHost.h"
diff --git a/third_party/WebKit/Source/core/frame/BUILD.gn b/third_party/WebKit/Source/core/frame/BUILD.gn index e7753d5..42c3061b 100644 --- a/third_party/WebKit/Source/core/frame/BUILD.gn +++ b/third_party/WebKit/Source/core/frame/BUILD.gn
@@ -137,7 +137,6 @@ "WebFrameWidgetBase.h", "WebFrameWidgetImpl.cpp", "WebFrameWidgetImpl.h", - "WebLocalFrameBase.h", "WebLocalFrameImpl.cpp", "WebLocalFrameImpl.h", "WebViewFrameWidget.cpp",
diff --git a/third_party/WebKit/Source/core/frame/Settings.json5 b/third_party/WebKit/Source/core/frame/Settings.json5 index 8f8539a..22373bb 100644 --- a/third_party/WebKit/Source/core/frame/Settings.json5 +++ b/third_party/WebKit/Source/core/frame/Settings.json5
@@ -594,6 +594,14 @@ invalidate: "DOMWorlds", }, + // Forces TouchEventFeatureDetection conditional feature for all main + // worlds in the page. Used by inspector to emulate touch on devices + // which don't support it naturally. + { + name: "forceTouchEventFeatureDetectionForInspector", + initial: false, + }, + // Compensates for poor text legibility on mobile devices. This value is // multiplied by the font scale factor when performing text autosizing of // websites that do not set an explicit viewport description.
diff --git a/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp b/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp index f17ca26..61bc88f 100644 --- a/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp +++ b/third_party/WebKit/Source/core/frame/VisualViewportTest.cpp
@@ -86,7 +86,7 @@ override_settings_func = &ConfigureSettings; helper_.Initialize(nullptr, &mock_web_view_client_, nullptr, override_settings_func); - WebViewImpl()->SetDefaultPageScaleLimits(1, 4); + WebView()->SetDefaultPageScaleLimits(1, 4); } void InitializeWithAndroidSettings( @@ -95,7 +95,7 @@ override_settings_func = &ConfigureAndroidSettings; helper_.Initialize(nullptr, &mock_web_view_client_, nullptr, override_settings_func); - WebViewImpl()->SetDefaultPageScaleLimits(0.25f, 5); + WebView()->SetDefaultPageScaleLimits(0.25f, 5); } ~VisualViewportTest() override { @@ -105,12 +105,10 @@ } void NavigateTo(const std::string& url) { - FrameTestHelpers::LoadFrame(WebViewImpl()->MainFrameImpl(), url); + FrameTestHelpers::LoadFrame(WebView()->MainFrameImpl(), url); } - void ForceFullCompositingUpdate() { - WebViewImpl()->UpdateAllLifecyclePhases(); - } + void ForceFullCompositingUpdate() { WebView()->UpdateAllLifecyclePhases(); } void RegisterMockedHttpURLLoad(const std::string& fileName) { URLTestHelpers::RegisterMockedURLLoadFromBase( @@ -125,7 +123,7 @@ blink::testing::CoreTestDataPath(WebString::FromUTF8(fileName))); } - WebViewBase* WebViewImpl() const { return helper_.WebView(); } + WebViewImpl* WebView() const { return helper_.WebView(); } LocalFrame* GetFrame() const { return helper_.LocalMainFrame()->GetFrame(); } static void ConfigureSettings(WebSettings* settings) { @@ -155,28 +153,28 @@ // WebView resizes the VisualViewport. TEST_P(VisualViewportTest, TestResize) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(320, 240)); + WebView()->Resize(IntSize(320, 240)); NavigateTo("about:blank"); ForceFullCompositingUpdate(); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); - IntSize web_view_size = WebViewImpl()->Size(); + IntSize web_view_size = WebView()->Size(); // Make sure the visual viewport was initialized. EXPECT_SIZE_EQ(web_view_size, visual_viewport.Size()); // Resizing the WebView should change the VisualViewport. web_view_size = IntSize(640, 480); - WebViewImpl()->Resize(web_view_size); - EXPECT_SIZE_EQ(web_view_size, IntSize(WebViewImpl()->Size())); + WebView()->Resize(web_view_size); + EXPECT_SIZE_EQ(web_view_size, IntSize(WebView()->Size())); EXPECT_SIZE_EQ(web_view_size, visual_viewport.Size()); // Resizing the visual viewport shouldn't affect the WebView. IntSize new_viewport_size = IntSize(320, 200); visual_viewport.SetSize(new_viewport_size); - EXPECT_SIZE_EQ(web_view_size, IntSize(WebViewImpl()->Size())); + EXPECT_SIZE_EQ(web_view_size, IntSize(WebView()->Size())); EXPECT_SIZE_EQ(new_viewport_size, visual_viewport.Size()); } @@ -193,10 +191,10 @@ // Vertical scrollbar width and horizontal scrollbar height. IntSize scrollbar_size = IntSize(15, 15); - WebViewImpl()->Resize(size); + WebView()->Resize(size); // Scroll layout viewport and verify visibleContentRect. - WebViewImpl()->MainFrameImpl()->SetScrollOffset(WebSize(0, 50)); + WebView()->MainFrameImpl()->SetScrollOffset(WebSize(0, 50)); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); EXPECT_EQ(IntRect(IntPoint(0, 0), size - scrollbar_size), @@ -204,7 +202,7 @@ EXPECT_EQ(IntRect(IntPoint(0, 0), size), visual_viewport.VisibleContentRect(kIncludeScrollbars)); - WebViewImpl()->SetPageScaleFactor(2.0); + WebView()->SetPageScaleFactor(2.0); // Scroll visual viewport and verify visibleContentRect. size.Scale(0.5); @@ -223,12 +221,12 @@ // make it appear to stay still). This caused bugs like crbug.com/453859. TEST_P(VisualViewportTest, TestResizeAtFullyScrolledPreservesViewportLocation) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(800, 600)); + WebView()->Resize(IntSize(800, 600)); RegisterMockedHttpURLLoad("content-width-1000.html"); NavigateTo(base_url_ + "content-width-1000.html"); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); visual_viewport.SetScale(2); @@ -249,13 +247,13 @@ // Shrink the WebView, this should cause both viewports to shrink and // WebView should do whatever it needs to do to preserve the visible // location. - WebViewImpl()->Resize(IntSize(700, 550)); + WebView()->Resize(IntSize(700, 550)); EXPECT_POINT_EQ( expected_location, frame_view.GetScrollableArea()->VisibleContentRect().Location()); - WebViewImpl()->Resize(IntSize(800, 600)); + WebView()->Resize(IntSize(800, 600)); EXPECT_POINT_EQ( expected_location, @@ -294,15 +292,15 @@ RegisterMockedHttpURLLoad("200-by-800-viewport.html"); NavigateTo(base_url_ + "200-by-800-viewport.html"); - WebViewImpl()->Resize(IntSize(100, 200)); + WebView()->Resize(IntSize(100, 200)); // Scroll main frame to the bottom of the document - WebViewImpl()->MainFrameImpl()->SetScrollOffset(WebSize(0, 400)); + WebView()->MainFrameImpl()->SetScrollOffset(WebSize(0, 400)); EXPECT_SIZE_EQ( ScrollOffset(0, 400), GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset()); - WebViewImpl()->SetPageScaleFactor(2.0); + WebView()->SetPageScaleFactor(2.0); // Scroll visual viewport to the bottom of the main frame VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); @@ -314,7 +312,7 @@ visual_viewport.VisibleRect().Size()); // Perform the resizing - WebViewImpl()->Resize(IntSize(200, 100)); + WebView()->Resize(IntSize(200, 100)); // After resizing the scale changes 2.0 -> 4.0 EXPECT_FLOAT_SIZE_EQ(FloatSize(50, 25), visual_viewport.VisibleRect().Size()); @@ -359,11 +357,11 @@ RegisterMockedHttpURLLoad("200-by-800-viewport.html"); NavigateTo(base_url_ + "200-by-800-viewport.html"); - WebViewImpl()->Resize(IntSize(100, 200)); + WebView()->Resize(IntSize(100, 200)); // Outer viewport takes the whole width of the document. - WebViewImpl()->SetPageScaleFactor(2.0); + WebView()->SetPageScaleFactor(2.0); // Scroll visual viewport to the right edge of the frame VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); @@ -374,7 +372,7 @@ EXPECT_FLOAT_SIZE_EQ(FloatSize(50, 100), visual_viewport.VisibleRect().Size()); - WebViewImpl()->Resize(IntSize(200, 100)); + WebView()->Resize(IntSize(200, 100)); // After resizing the scale changes 2.0 -> 4.0 EXPECT_FLOAT_SIZE_EQ(FloatSize(50, 25), visual_viewport.VisibleRect().Size()); @@ -387,17 +385,17 @@ // prior to the VisualViewport being attached to the layer tree. TEST_P(VisualViewportTest, TestWebViewResizedBeforeAttachment) { InitializeWithDesktopSettings(); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); // Make sure that a resize that comes in while there's no root layer is // honoured when we attach to the layer tree. WebFrameWidgetBase* main_frame_widget = - WebViewImpl()->MainFrameImpl()->FrameWidget(); + WebView()->MainFrameImpl()->FrameWidget(); main_frame_widget->SetRootGraphicsLayer(nullptr); - WebViewImpl()->Resize(IntSize(320, 240)); + WebView()->Resize(IntSize(320, 240)); NavigateTo("about:blank"); - WebViewImpl()->UpdateAllLifecyclePhases(); + WebView()->UpdateAllLifecyclePhases(); main_frame_widget->SetRootGraphicsLayer( frame_view.GetLayoutViewItem().Compositor()->RootGraphicsLayer()); @@ -410,7 +408,7 @@ // location of the viewport. TEST_P(VisualViewportTest, TestVisibleRect) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(320, 240)); + WebView()->Resize(IntSize(320, 240)); NavigateTo("about:blank"); ForceFullCompositingUpdate(); @@ -418,12 +416,12 @@ VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); // Initial visible rect should be the whole frame. - EXPECT_SIZE_EQ(IntSize(WebViewImpl()->Size()), visual_viewport.Size()); + EXPECT_SIZE_EQ(IntSize(WebView()->Size()), visual_viewport.Size()); // Viewport is whole frame. IntSize size = IntSize(400, 200); - WebViewImpl()->Resize(size); - WebViewImpl()->UpdateAllLifecyclePhases(); + WebView()->Resize(size); + WebView()->UpdateAllLifecyclePhases(); visual_viewport.SetSize(size); // Scale the viewport to 2X; size should not change. @@ -460,7 +458,7 @@ // and scroll location of the viewport relative to the document. TEST_P(VisualViewportTest, TestVisibleRectInDocument) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(100, 400)); + WebView()->Resize(IntSize(100, 400)); RegisterMockedHttpURLLoad("200-by-800-viewport.html"); NavigateTo(base_url_ + "200-by-800-viewport.html"); @@ -475,7 +473,7 @@ // Scroll the layout viewport. Ensure its offset is reflected in // visibleRectInDocument(). - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); frame_view.LayoutViewportScrollableArea()->SetScrollOffset( ScrollOffset(40, 100), kProgrammaticScroll); EXPECT_FLOAT_RECT_EQ(FloatRect(50, 115, 50, 200), @@ -488,12 +486,12 @@ RuntimeEnabledFeatures::SetFractionalScrollOffsetsEnabled(true); InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(200, 250)); + WebView()->Resize(IntSize(200, 250)); RegisterMockedHttpURLLoad("200-by-800-viewport.html"); NavigateTo(base_url_ + "200-by-800-viewport.html"); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); frame_view.LayoutViewportScrollableArea()->SetScrollOffset( ScrollOffset(0, 10.5), kProgrammaticScroll); frame_view.LayoutViewportScrollableArea()->ScrollableArea::SetScrollOffset( @@ -511,7 +509,7 @@ // that the visual viewport always stays within the bounds of the main frame. TEST_P(VisualViewportTest, TestOffsetClamping) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(320, 240)); + WebView()->Resize(IntSize(320, 240)); NavigateTo("about:blank"); ForceFullCompositingUpdate(); @@ -566,7 +564,7 @@ // keyboard came up. TEST_P(VisualViewportTest, TestOffsetClampingWithResize) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(320, 240)); + WebView()->Resize(IntSize(320, 240)); NavigateTo("about:blank"); ForceFullCompositingUpdate(); @@ -634,7 +632,7 @@ // main frame when we apply both scaling and resizes. TEST_P(VisualViewportTest, TestOffsetClampingWithResizeAndScale) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(320, 240)); + WebView()->Resize(IntSize(320, 240)); NavigateTo("about:blank"); ForceFullCompositingUpdate(); @@ -665,10 +663,10 @@ EXPECT_SIZE_EQ(IntSize(330, 250), visual_viewport.Size()); // Resize both the viewport and the frame to be larger. - WebViewImpl()->Resize(IntSize(640, 480)); - WebViewImpl()->UpdateAllLifecyclePhases(); - EXPECT_SIZE_EQ(IntSize(WebViewImpl()->Size()), visual_viewport.Size()); - EXPECT_SIZE_EQ(IntSize(WebViewImpl()->Size()), + WebView()->Resize(IntSize(640, 480)); + WebView()->UpdateAllLifecyclePhases(); + EXPECT_SIZE_EQ(IntSize(WebView()->Size()), visual_viewport.Size()); + EXPECT_SIZE_EQ(IntSize(WebView()->Size()), GetFrame()->View()->FrameRect().Size()); visual_viewport.SetLocation(FloatPoint(1000, 1000)); EXPECT_FLOAT_POINT_EQ(FloatPoint(320, 240), @@ -688,19 +686,19 @@ // the aspect ratio. TEST_P(VisualViewportTest, TestFrameViewSizedToContent) { InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(320, 240)); + WebView()->Resize(IntSize(320, 240)); RegisterMockedHttpURLLoad("200-by-300-viewport.html"); NavigateTo(base_url_ + "200-by-300-viewport.html"); - WebViewImpl()->Resize(IntSize(600, 800)); - WebViewImpl()->UpdateAllLifecyclePhases(); + WebView()->Resize(IntSize(600, 800)); + WebView()->UpdateAllLifecyclePhases(); // Note: the size is ceiled and should match the behavior in CC's // LayerImpl::bounds(). EXPECT_SIZE_EQ( IntSize(200, 267), - WebViewImpl()->MainFrameImpl()->GetFrameView()->FrameRect().Size()); + WebView()->MainFrameImpl()->GetFrameView()->FrameRect().Size()); } // The main LocalFrameView's size should be set such that its the size of the @@ -708,30 +706,30 @@ // so make sure the LocalFrameView is sized to the viewport. TEST_P(VisualViewportTest, TestFrameViewSizedToMinimumScale) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(320, 240)); + WebView()->Resize(IntSize(320, 240)); RegisterMockedHttpURLLoad("200-by-300.html"); NavigateTo(base_url_ + "200-by-300.html"); - WebViewImpl()->Resize(IntSize(100, 160)); - WebViewImpl()->UpdateAllLifecyclePhases(); + WebView()->Resize(IntSize(100, 160)); + WebView()->UpdateAllLifecyclePhases(); EXPECT_SIZE_EQ( IntSize(100, 160), - WebViewImpl()->MainFrameImpl()->GetFrameView()->FrameRect().Size()); + WebView()->MainFrameImpl()->GetFrameView()->FrameRect().Size()); } // Test that attaching a new frame view resets the size of the inner viewport // scroll layer. crbug.com/423189. TEST_P(VisualViewportTest, TestAttachingNewFrameSetsInnerScrollLayerSize) { InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(320, 240)); + WebView()->Resize(IntSize(320, 240)); // Load a wider page first, the navigation should resize the scroll layer to // the smaller size on the second navigation. RegisterMockedHttpURLLoad("content-width-1000.html"); NavigateTo(base_url_ + "content-width-1000.html"); - WebViewImpl()->UpdateAllLifecyclePhases(); + WebView()->UpdateAllLifecyclePhases(); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); visual_viewport.SetScale(2); @@ -762,28 +760,28 @@ // appropriately sized in the presence of a viewport <meta> tag. TEST_P(VisualViewportTest, TestFrameViewSizedToViewportMetaMinimumScale) { InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(320, 240)); + WebView()->Resize(IntSize(320, 240)); RegisterMockedHttpURLLoad("200-by-300-min-scale-2.html"); NavigateTo(base_url_ + "200-by-300-min-scale-2.html"); - WebViewImpl()->Resize(IntSize(100, 160)); - WebViewImpl()->UpdateAllLifecyclePhases(); + WebView()->Resize(IntSize(100, 160)); + WebView()->UpdateAllLifecyclePhases(); EXPECT_SIZE_EQ( IntSize(50, 80), - WebViewImpl()->MainFrameImpl()->GetFrameView()->FrameRect().Size()); + WebView()->MainFrameImpl()->GetFrameView()->FrameRect().Size()); } // Test that the visual viewport still gets sized in AutoSize/AutoResize mode. TEST_P(VisualViewportTest, TestVisualViewportGetsSizeInAutoSizeMode) { InitializeWithDesktopSettings(); - EXPECT_SIZE_EQ(IntSize(0, 0), IntSize(WebViewImpl()->Size())); + EXPECT_SIZE_EQ(IntSize(0, 0), IntSize(WebView()->Size())); EXPECT_SIZE_EQ(IntSize(0, 0), GetFrame()->GetPage()->GetVisualViewport().Size()); - WebViewImpl()->EnableAutoResizeMode(WebSize(10, 10), WebSize(1000, 1000)); + WebView()->EnableAutoResizeMode(WebSize(10, 10), WebSize(1000, 1000)); RegisterMockedHttpURLLoad("200-by-300.html"); NavigateTo(base_url_ + "200-by-300.html"); @@ -796,24 +794,24 @@ // viewport. TEST_P(VisualViewportTest, TestTextSelectionHandles) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(500, 800)); + WebView()->Resize(IntSize(500, 800)); RegisterMockedHttpURLLoad("pinch-viewport-input-field.html"); NavigateTo(base_url_ + "pinch-viewport-input-field.html"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); - WebViewImpl()->SetInitialFocus(false); + WebView()->SetInitialFocus(false); WebRect original_anchor; WebRect original_focus; - WebViewImpl()->SelectionBounds(original_anchor, original_focus); + WebView()->SelectionBounds(original_anchor, original_focus); - WebViewImpl()->SetPageScaleFactor(2); + WebView()->SetPageScaleFactor(2); visual_viewport.SetLocation(FloatPoint(100, 400)); WebRect anchor; WebRect focus; - WebViewImpl()->SelectionBounds(anchor, focus); + WebView()->SelectionBounds(anchor, focus); IntPoint expected(IntRect(original_anchor).Location()); expected.MoveBy(-FlooredIntPoint(visual_viewport.VisibleRect().Location())); @@ -830,13 +828,13 @@ // and scale. TEST_P(VisualViewportTest, TestSavedToHistoryItem) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(200, 300)); - WebViewImpl()->UpdateAllLifecyclePhases(); + WebView()->Resize(IntSize(200, 300)); + WebView()->UpdateAllLifecyclePhases(); RegisterMockedHttpURLLoad("200-by-300.html"); NavigateTo(base_url_ + "200-by-300.html"); - EXPECT_EQ(nullptr, ToLocalFrame(WebViewImpl()->GetPage()->MainFrame()) + EXPECT_EQ(nullptr, ToLocalFrame(WebView()->GetPage()->MainFrame()) ->Loader() .GetDocumentLoader() ->GetHistoryItem() @@ -845,7 +843,7 @@ VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); visual_viewport.SetScale(2); - EXPECT_EQ(2, ToLocalFrame(WebViewImpl()->GetPage()->MainFrame()) + EXPECT_EQ(2, ToLocalFrame(WebView()->GetPage()->MainFrame()) ->Loader() .GetDocumentLoader() ->GetHistoryItem() @@ -855,7 +853,7 @@ visual_viewport.SetLocation(FloatPoint(10, 20)); EXPECT_SIZE_EQ(ScrollOffset(10, 20), - ToLocalFrame(WebViewImpl()->GetPage()->MainFrame()) + ToLocalFrame(WebView()->GetPage()->MainFrame()) ->Loader() .GetDocumentLoader() ->GetHistoryItem() @@ -866,7 +864,7 @@ // Test restoring a HistoryItem properly restores the visual viewport's state. TEST_P(VisualViewportTest, TestRestoredFromHistoryItem) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(200, 300)); + WebView()->Resize(IntSize(200, 300)); RegisterMockedHttpURLLoad("200-by-300.html"); @@ -877,7 +875,7 @@ item.SetVisualViewportScrollOffset(WebFloatPoint(100, 120)); item.SetPageScaleFactor(2); - FrameTestHelpers::LoadHistoryItem(WebViewImpl()->MainFrameImpl(), item, + FrameTestHelpers::LoadHistoryItem(WebView()->MainFrameImpl(), item, kWebHistoryDifferentDocumentLoad, WebCachePolicy::kUseProtocolCachePolicy); @@ -893,7 +891,7 @@ // viewport. TEST_P(VisualViewportTest, TestRestoredFromLegacyHistoryItem) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(100, 150)); + WebView()->Resize(IntSize(100, 150)); RegisterMockedHttpURLLoad("200-by-300-viewport.html"); @@ -908,7 +906,7 @@ item.SetScrollOffset(WebPoint(120, 180)); item.SetPageScaleFactor(2); - FrameTestHelpers::LoadHistoryItem(WebViewImpl()->MainFrameImpl(), item, + FrameTestHelpers::LoadHistoryItem(WebView()->MainFrameImpl(), item, kWebHistoryDifferentDocumentLoad, WebCachePolicy::kUseProtocolCachePolicy); @@ -926,13 +924,13 @@ TEST_P(VisualViewportTest, TestNavigateToSmallerFrameViewHistoryItemClobberBug) { InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(400, 400)); - WebViewImpl()->UpdateAllLifecyclePhases(); + WebView()->Resize(IntSize(400, 400)); + WebView()->UpdateAllLifecyclePhases(); RegisterMockedHttpURLLoad("content-width-1000.html"); NavigateTo(base_url_ + "content-width-1000.html"); - LocalFrameView* frame_view = WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView* frame_view = WebView()->MainFrameImpl()->GetFrameView(); frame_view->LayoutViewportScrollableArea()->SetScrollOffset( ScrollOffset(0, 1000), kProgrammaticScroll); @@ -942,7 +940,7 @@ visual_viewport.SetScale(2); visual_viewport.SetLocation(FloatPoint(350, 350)); - Persistent<HistoryItem> firstItem = WebViewImpl() + Persistent<HistoryItem> firstItem = WebView() ->MainFrameImpl() ->GetFrame() ->Loader() @@ -955,9 +953,9 @@ // navigating doesn't cause the history item to set a new scroll offset // before the item was replaced. NavigateTo("about:blank"); - frame_view = WebViewImpl()->MainFrameImpl()->GetFrameView(); + frame_view = WebView()->MainFrameImpl()->GetFrameView(); - EXPECT_NE(firstItem, WebViewImpl() + EXPECT_NE(firstItem, WebView() ->MainFrameImpl() ->GetFrame() ->Loader() @@ -973,16 +971,16 @@ TEST_P(VisualViewportTest, DISABLED_TestWebFrameRangeAccountsForVisualViewportScroll) { InitializeWithDesktopSettings(); - WebViewImpl()->GetSettings()->SetDefaultFontSize(12); - WebViewImpl()->Resize(WebSize(640, 480)); + WebView()->GetSettings()->SetDefaultFontSize(12); + WebView()->Resize(WebSize(640, 480)); RegisterMockedHttpURLLoad("move_range.html"); NavigateTo(base_url_ + "move_range.html"); WebRect base_rect; WebRect extent_rect; - WebViewImpl()->SetPageScaleFactor(2); - WebLocalFrame* mainFrame = WebViewImpl()->MainFrameImpl(); + WebView()->SetPageScaleFactor(2); + WebLocalFrame* mainFrame = WebView()->MainFrameImpl(); // Select some text and get the base and extent rects (that's the start of // the range and its end). Do a sanity check that the expected text is @@ -990,7 +988,7 @@ mainFrame->ExecuteScript(WebScriptSource("selectRange();")); EXPECT_EQ("ir", mainFrame->SelectionAsText().Utf8()); - WebViewImpl()->SelectionBounds(base_rect, extent_rect); + WebView()->SelectionBounds(base_rect, extent_rect); WebPoint initialPoint(base_rect.x, base_rect.y); WebPoint endPoint(extent_rect.x, extent_rect.y); @@ -1007,16 +1005,16 @@ // visual viewport. TEST_P(VisualViewportTest, DISABLED_TestScrollFocusedEditableElementIntoRect) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(500, 300)); + WebView()->Resize(IntSize(500, 300)); RegisterMockedHttpURLLoad("pinch-viewport-input-field.html"); NavigateTo(base_url_ + "pinch-viewport-input-field.html"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); - WebViewImpl()->ResizeVisualViewport(IntSize(200, 100)); - WebViewImpl()->SetInitialFocus(false); + WebView()->ResizeVisualViewport(IntSize(200, 100)); + WebView()->SetInitialFocus(false); visual_viewport.SetLocation(FloatPoint()); - WebViewImpl()->ScrollFocusedEditableElementIntoRect(IntRect(0, 0, 500, 200)); + WebView()->ScrollFocusedEditableElementIntoRect(IntRect(0, 0, 500, 200)); EXPECT_SIZE_EQ( ScrollOffset(0, GetFrame()->View()->MaximumScrollOffset().Height()), @@ -1026,11 +1024,11 @@ // Try it again but with the page zoomed in GetFrame()->View()->SetScrollOffset(ScrollOffset(0, 0), kProgrammaticScroll); - WebViewImpl()->ResizeVisualViewport(IntSize(500, 300)); + WebView()->ResizeVisualViewport(IntSize(500, 300)); visual_viewport.SetLocation(FloatPoint(0, 0)); - WebViewImpl()->SetPageScaleFactor(2); - WebViewImpl()->ScrollFocusedEditableElementIntoRect(IntRect(0, 0, 500, 200)); + WebView()->SetPageScaleFactor(2); + WebView()->ScrollFocusedEditableElementIntoRect(IntRect(0, 0, 500, 200)); EXPECT_SIZE_EQ( ScrollOffset(0, GetFrame()->View()->MaximumScrollOffset().Height()), GetFrame()->View()->GetScrollOffset()); @@ -1041,14 +1039,14 @@ // necessary. RegisterMockedHttpURLLoad("pinch-viewport-input-field-long-and-wide.html"); NavigateTo(base_url_ + "pinch-viewport-input-field-long-and-wide.html"); - WebViewImpl()->SetInitialFocus(false); + WebView()->SetInitialFocus(false); visual_viewport.SetLocation(FloatPoint()); GetFrame()->View()->SetScrollOffset(ScrollOffset(0, 0), kProgrammaticScroll); - WebViewImpl()->ResizeVisualViewport(IntSize(500, 300)); + WebView()->ResizeVisualViewport(IntSize(500, 300)); visual_viewport.SetLocation(FloatPoint(30, 50)); - WebViewImpl()->SetPageScaleFactor(2); - WebViewImpl()->ScrollFocusedEditableElementIntoRect(IntRect(0, 0, 500, 200)); + WebView()->SetPageScaleFactor(2); + WebView()->ScrollFocusedEditableElementIntoRect(IntRect(0, 0, 500, 200)); EXPECT_SIZE_EQ(ScrollOffset(200 - 30 - 75, 600 - 50 - 65), GetFrame()->View()->GetScrollOffset()); EXPECT_FLOAT_POINT_EQ(FloatPoint(30, 50), @@ -1059,7 +1057,7 @@ // relayout. TEST_P(VisualViewportTest, TestWebViewResizeCausesViewportConstrainedLayout) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(500, 300)); + WebView()->Resize(IntSize(500, 300)); RegisterMockedHttpURLLoad("pinch-viewport-fixed-pos.html"); NavigateTo(base_url_ + "pinch-viewport-fixed-pos.html"); @@ -1093,7 +1091,7 @@ // viewport offset. TEST_P(VisualViewportTest, TestContextMenuShownInCorrectLocation) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(200, 300)); + WebView()->Resize(IntSize(200, 300)); RegisterMockedHttpURLLoad("200-by-300.html"); NavigateTo(base_url_ + "200-by-300.html"); @@ -1110,7 +1108,7 @@ WebMouseEvent mouse_up_event(mouse_down_event); mouse_up_event.SetType(WebInputEvent::kMouseUp); - WebFrameClient* old_client = WebViewImpl()->MainFrameImpl()->Client(); + WebFrameClient* old_client = WebView()->MainFrameImpl()->Client(); VisualViewportMockWebFrameClient mock_web_frame_client; EXPECT_CALL(mock_web_frame_client, ShowContextMenu(ContextMenuAtLocation( @@ -1118,18 +1116,18 @@ mouse_down_event.PositionInWidget().y))); // Do a sanity check with no scale applied. - WebViewImpl()->MainFrameImpl()->SetClient(&mock_web_frame_client); - WebViewImpl()->HandleInputEvent(WebCoalescedInputEvent(mouse_down_event)); - WebViewImpl()->HandleInputEvent(WebCoalescedInputEvent(mouse_up_event)); + WebView()->MainFrameImpl()->SetClient(&mock_web_frame_client); + WebView()->HandleInputEvent(WebCoalescedInputEvent(mouse_down_event)); + WebView()->HandleInputEvent(WebCoalescedInputEvent(mouse_up_event)); Mock::VerifyAndClearExpectations(&mock_web_frame_client); mouse_down_event.button = WebMouseEvent::Button::kLeft; - WebViewImpl()->HandleInputEvent(WebCoalescedInputEvent(mouse_down_event)); + WebView()->HandleInputEvent(WebCoalescedInputEvent(mouse_down_event)); // Now pinch zoom into the page and move the visual viewport. The context menu // should still appear at the location of the event, relative to the WebView. VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); - WebViewImpl()->SetPageScaleFactor(2); + WebView()->SetPageScaleFactor(2); EXPECT_CALL(mock_web_frame_client, DidChangeScrollOffset()); visual_viewport.SetLocation(FloatPoint(60, 80)); EXPECT_CALL(mock_web_frame_client, @@ -1138,26 +1136,26 @@ mouse_down_event.PositionInWidget().y))); mouse_down_event.button = WebMouseEvent::Button::kRight; - WebViewImpl()->HandleInputEvent(WebCoalescedInputEvent(mouse_down_event)); - WebViewImpl()->HandleInputEvent(WebCoalescedInputEvent(mouse_up_event)); + WebView()->HandleInputEvent(WebCoalescedInputEvent(mouse_down_event)); + WebView()->HandleInputEvent(WebCoalescedInputEvent(mouse_up_event)); // Reset the old client so destruction can occur naturally. - WebViewImpl()->MainFrameImpl()->SetClient(old_client); + WebView()->MainFrameImpl()->SetClient(old_client); } // Test that the client is notified if page scroll events. TEST_P(VisualViewportTest, TestClientNotifiedOfScrollEvents) { InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(200, 300)); + WebView()->Resize(IntSize(200, 300)); RegisterMockedHttpURLLoad("200-by-300.html"); NavigateTo(base_url_ + "200-by-300.html"); - WebFrameClient* old_client = WebViewImpl()->MainFrameImpl()->Client(); + WebFrameClient* old_client = WebView()->MainFrameImpl()->Client(); VisualViewportMockWebFrameClient mock_web_frame_client; - WebViewImpl()->MainFrameImpl()->SetClient(&mock_web_frame_client); + WebView()->MainFrameImpl()->SetClient(&mock_web_frame_client); - WebViewImpl()->SetPageScaleFactor(2); + WebView()->SetPageScaleFactor(2); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); EXPECT_CALL(mock_web_frame_client, DidChangeScrollOffset()); @@ -1174,7 +1172,7 @@ visual_viewport.SetLocation(FloatPoint(70, 90)); // Reset the old client so destruction can occur naturally. - WebViewImpl()->MainFrameImpl()->SetClient(old_client); + WebView()->MainFrameImpl()->SetClient(old_client); } // Tests that calling scroll into view on a visible element doesn't cause @@ -1182,22 +1180,22 @@ TEST_P(VisualViewportTest, ScrollIntoViewFractionalOffset) { InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(1000, 1000)); + WebView()->Resize(IntSize(1000, 1000)); RegisterMockedHttpURLLoad("scroll-into-view.html"); NavigateTo(base_url_ + "scroll-into-view.html"); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); ScrollableArea* layout_viewport_scrollable_area = frame_view.LayoutViewportScrollableArea(); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); Element* inputBox = GetFrame()->GetDocument()->getElementById("box"); - WebViewImpl()->SetPageScaleFactor(2); + WebView()->SetPageScaleFactor(2); // The element is already in the view so the scrollIntoView shouldn't move // the viewport at all. - WebViewImpl()->SetVisualViewportOffset(WebFloatPoint(250.25f, 100.25f)); + WebView()->SetVisualViewportOffset(WebFloatPoint(250.25f, 100.25f)); layout_viewport_scrollable_area->SetScrollOffset(ScrollOffset(0, 900.75), kProgrammaticScroll); inputBox->scrollIntoViewIfNeeded(false); @@ -1218,7 +1216,7 @@ visual_viewport.GetScrollOffset()); // Repeat both tests above with the visual viewport at a high fractional. - WebViewImpl()->SetVisualViewportOffset(WebFloatPoint(250.875f, 100.875f)); + WebView()->SetVisualViewportOffset(WebFloatPoint(250.875f, 100.875f)); layout_viewport_scrollable_area->SetScrollOffset(ScrollOffset(0, 900.75), kProgrammaticScroll); inputBox->scrollIntoViewIfNeeded(false); @@ -1239,7 +1237,7 @@ visual_viewport.GetScrollOffset()); // Both viewports with a 0.5 fraction. - WebViewImpl()->SetVisualViewportOffset(WebFloatPoint(250.5f, 100.5f)); + WebView()->SetVisualViewportOffset(WebFloatPoint(250.5f, 100.5f)); layout_viewport_scrollable_area->SetScrollOffset(ScrollOffset(0, 900.5), kProgrammaticScroll); inputBox->scrollIntoViewIfNeeded(false); @@ -1262,21 +1260,21 @@ TEST_P(VisualViewportTest, TestBrowserControlsAdjustment) { InitializeWithAndroidSettings(); - WebViewImpl()->ResizeWithBrowserControls(IntSize(500, 450), 20, 0, false); + WebView()->ResizeWithBrowserControls(IntSize(500, 450), 20, 0, false); RegisterMockedHttpURLLoad("content-width-1000.html"); NavigateTo(base_url_ + "content-width-1000.html"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); visual_viewport.SetScale(1); EXPECT_SIZE_EQ(IntSize(500, 450), visual_viewport.VisibleRect().Size()); EXPECT_SIZE_EQ(IntSize(1000, 900), frame_view.FrameRect().Size()); // Simulate bringing down the browser controls by 20px. - WebViewImpl()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), - WebFloatSize(), 1, 1); + WebView()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(), + 1, 1); EXPECT_SIZE_EQ(IntSize(500, 430), visual_viewport.VisibleRect().Size()); // Test that the scroll bounds are adjusted appropriately: the visual viewport @@ -1293,8 +1291,8 @@ frame_view.LayoutViewportScrollableArea()->GetScrollOffset()); // Simulate bringing up the browser controls by 10.5px. - WebViewImpl()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), - WebFloatSize(), 1, -10.5f / 20); + WebView()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(), + 1, -10.5f / 20); EXPECT_FLOAT_SIZE_EQ(FloatSize(500, 440.5f), visual_viewport.VisibleRect().Size()); @@ -1312,13 +1310,13 @@ TEST_P(VisualViewportTest, TestBrowserControlsAdjustmentWithScale) { InitializeWithAndroidSettings(); - WebViewImpl()->ResizeWithBrowserControls(IntSize(500, 450), 20, 0, false); + WebView()->ResizeWithBrowserControls(IntSize(500, 450), 20, 0, false); RegisterMockedHttpURLLoad("content-width-1000.html"); NavigateTo(base_url_ + "content-width-1000.html"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); visual_viewport.SetScale(2); EXPECT_SIZE_EQ(IntSize(250, 225), visual_viewport.VisibleRect().Size()); @@ -1327,8 +1325,8 @@ // Simulate bringing down the browser controls by 20px. Since we're zoomed in, // the browser controls take up half as much space (in document-space) than // they do at an unzoomed level. - WebViewImpl()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), - WebFloatSize(), 1, 1); + WebView()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(), + 1, 1); EXPECT_SIZE_EQ(IntSize(250, 215), visual_viewport.VisibleRect().Size()); // Test that the scroll bounds are adjusted appropriately. @@ -1345,8 +1343,8 @@ // Scale back out, LocalFrameView max scroll shouldn't have changed. Visual // viewport should be moved up to accomodate larger view. - WebViewImpl()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), - WebFloatSize(), 0.5f, 0); + WebView()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(), + 0.5f, 0); EXPECT_EQ(1, visual_viewport.Scale()); EXPECT_SIZE_EQ(expected, frame_view.LayoutViewportScrollableArea()->GetScrollOffset()); @@ -1360,13 +1358,13 @@ EXPECT_SIZE_EQ(FloatSize(500, 860 - 430), visual_viewport.GetScrollOffset()); // Scale out, use a scale that causes fractional rects. - WebViewImpl()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), - WebFloatSize(), 0.8f, -1); + WebView()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(), + 0.8f, -1); EXPECT_SIZE_EQ(FloatSize(625, 562.5), visual_viewport.VisibleRect().Size()); // Bring out the browser controls by 11 - WebViewImpl()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), - WebFloatSize(), 1, 11 / 20.f); + WebView()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(), + 1, 11 / 20.f); EXPECT_SIZE_EQ(FloatSize(625, 548.75), visual_viewport.VisibleRect().Size()); // Ensure max scroll offsets are updated properly. @@ -1393,16 +1391,16 @@ InitializeWithAndroidSettings(); // Initialize with browser controls showing and shrinking the Blink size. - WebViewImpl()->ResizeWithBrowserControls( + WebView()->ResizeWithBrowserControls( WebSize(500, visual_viewport_height - browser_controls_height), 20, 0, true); - WebViewImpl()->GetBrowserControls().SetShownRatio(1); + WebView()->GetBrowserControls().SetShownRatio(1); RegisterMockedHttpURLLoad("content-width-1000.html"); NavigateTo(base_url_ + "content-width-1000.html"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); visual_viewport.SetScale(page_scale); EXPECT_SIZE_EQ( @@ -1420,7 +1418,7 @@ visual_viewport.Move(ScrollOffset(10000, 10000)); frame_view.LayoutViewportScrollableArea()->ScrollBy( ScrollOffset(10000, 10000), kUserScroll); - WebViewImpl()->GetBrowserControls().SetShownRatio(0); + WebView()->GetBrowserControls().SetShownRatio(0); EXPECT_SIZE_EQ(IntSize(250, visual_viewport_height / page_scale), visual_viewport.VisibleRect().Size()); @@ -1439,8 +1437,8 @@ // Resize the widget to match the browser controls adjustment. Ensure that the // total offset (i.e. what the user sees) doesn't change because of clamping // the offsets to valid values. - WebViewImpl()->ResizeWithBrowserControls(WebSize(500, visual_viewport_height), - 20, 0, false); + WebView()->ResizeWithBrowserControls(WebSize(500, visual_viewport_height), 20, + 0, false); EXPECT_SIZE_EQ(IntSize(500, visual_viewport_height), visual_viewport.Size()); EXPECT_SIZE_EQ(IntSize(250, visual_viewport_height / page_scale), @@ -1467,15 +1465,15 @@ InitializeWithAndroidSettings(); // Initialize with browser controls hidden and not shrinking the Blink size. - WebViewImpl()->ResizeWithBrowserControls(IntSize(500, visual_viewport_height), - 20, 0, false); - WebViewImpl()->GetBrowserControls().SetShownRatio(0); + WebView()->ResizeWithBrowserControls(IntSize(500, visual_viewport_height), 20, + 0, false); + WebView()->GetBrowserControls().SetShownRatio(0); RegisterMockedHttpURLLoad("content-width-1000.html"); NavigateTo(base_url_ + "content-width-1000.html"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); visual_viewport.SetScale(page_scale); EXPECT_SIZE_EQ(IntSize(250, visual_viewport_height / page_scale), @@ -1487,7 +1485,7 @@ // Scroll all the way to the bottom, showing the the browser controls in the // process. (This could happen via window.scrollTo during a scroll, for // example). - WebViewImpl()->GetBrowserControls().SetShownRatio(1); + WebView()->GetBrowserControls().SetShownRatio(1); visual_viewport.Move(ScrollOffset(10000, 10000)); frame_view.LayoutViewportScrollableArea()->ScrollBy( ScrollOffset(10000, 10000), kUserScroll); @@ -1513,7 +1511,7 @@ // Resize the widget to match the browser controls adjustment. Ensure that the // total offset (i.e. what the user sees) doesn't change because of clamping // the offsets to valid values. - WebViewImpl()->ResizeWithBrowserControls( + WebView()->ResizeWithBrowserControls( WebSize(500, visual_viewport_height - browser_controls_height), 20, 0, true); @@ -1536,11 +1534,10 @@ // the main frame's scroll offset. crbug.com/428193. TEST_P(VisualViewportTest, TestTopControlHidingResizeDoesntClampMainFrame) { InitializeWithAndroidSettings(); - WebViewImpl()->ResizeWithBrowserControls(WebViewImpl()->Size(), 500, 0, - false); - WebViewImpl()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), - WebFloatSize(), 1, 1); - WebViewImpl()->ResizeWithBrowserControls(WebSize(1000, 1000), 500, 0, true); + WebView()->ResizeWithBrowserControls(WebView()->Size(), 500, 0, false); + WebView()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(), + 1, 1); + WebView()->ResizeWithBrowserControls(WebSize(1000, 1000), 500, 0, true); RegisterMockedHttpURLLoad("content-width-1000.html"); NavigateTo(base_url_ + "content-width-1000.html"); @@ -1548,9 +1545,9 @@ // Scroll the LocalFrameView to the bottom of the page but "hide" the browser // controls on the compositor side so the max scroll position should account // for the full viewport height. - WebViewImpl()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), - WebFloatSize(), 1, -1); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + WebView()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(), + 1, -1); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); frame_view.LayoutViewportScrollableArea()->SetScrollOffset( ScrollOffset(0, 10000), kProgrammaticScroll); EXPECT_EQ( @@ -1558,7 +1555,7 @@ frame_view.LayoutViewportScrollableArea()->GetScrollOffset().Height()); // Now send the resize, make sure the scroll offset doesn't change. - WebViewImpl()->ResizeWithBrowserControls(WebSize(1000, 1500), 500, 0, false); + WebView()->ResizeWithBrowserControls(WebSize(1000, 1500), 500, 0, false); EXPECT_EQ( 500, frame_view.LayoutViewportScrollableArea()->GetScrollOffset().Height()); @@ -1574,7 +1571,7 @@ TEST_P(VisualViewportTest, TestScrollbarsNotAttachedWhenHideScrollbarsSettingIsTrue) { InitializeWithAndroidSettings(configureHiddenScrollbarsSettings); - WebViewImpl()->Resize(IntSize(100, 150)); + WebView()->Resize(IntSize(100, 150)); NavigateTo("about:blank"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); @@ -1587,7 +1584,7 @@ TEST_P(VisualViewportTest, TestScrollbarsAttachedWhenHideScrollbarsSettingIsFalse) { InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(100, 150)); + WebView()->Resize(IntSize(100, 150)); NavigateTo("about:blank"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); @@ -1599,14 +1596,14 @@ // compositing change update. crbug.com/423188. TEST_P(VisualViewportTest, TestChangingContentSizeAffectsScrollBounds) { InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(100, 150)); + WebView()->Resize(IntSize(100, 150)); RegisterMockedHttpURLLoad("content-width-1000.html"); NavigateTo(base_url_ + "content-width-1000.html"); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); - WebViewImpl()->MainFrameImpl()->ExecuteScript( + WebView()->MainFrameImpl()->ExecuteScript( WebScriptSource("var content = document.getElementById(\"content\");" "content.style.width = \"1500px\";" "content.style.height = \"2400px\";")); @@ -1622,19 +1619,19 @@ // viewport. TEST_P(VisualViewportTest, ResizeVisualViewportStaysWithinOuterViewport) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(100, 200)); + WebView()->Resize(IntSize(100, 200)); NavigateTo("about:blank"); - WebViewImpl()->UpdateAllLifecyclePhases(); + WebView()->UpdateAllLifecyclePhases(); - WebViewImpl()->ResizeVisualViewport(IntSize(100, 100)); + WebView()->ResizeVisualViewport(IntSize(100, 100)); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); visual_viewport.Move(ScrollOffset(0, 100)); EXPECT_EQ(100, visual_viewport.GetScrollOffset().Height()); - WebViewImpl()->ResizeVisualViewport(IntSize(100, 200)); + WebView()->ResizeVisualViewport(IntSize(100, 200)); EXPECT_EQ(0, visual_viewport.GetScrollOffset().Height()); } @@ -1642,13 +1639,13 @@ TEST_P(VisualViewportTest, ElementBoundsInViewportSpaceAccountsForViewport) { InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(500, 800)); + WebView()->Resize(IntSize(500, 800)); RegisterMockedHttpURLLoad("pinch-viewport-input-field.html"); NavigateTo(base_url_ + "pinch-viewport-input-field.html"); - WebViewImpl()->SetInitialFocus(false); - Element* input_element = WebViewImpl()->FocusedElement(); + WebView()->SetInitialFocus(false); + Element* input_element = WebView()->FocusedElement(); IntRect bounds = input_element->GetLayoutObject()->AbsoluteBoundingBoxRect(); @@ -1670,16 +1667,16 @@ TEST_P(VisualViewportTest, ElementVisibleBoundsInVisualViewport) { InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(640, 1080)); + WebView()->Resize(IntSize(640, 1080)); RegisterMockedHttpURLLoad("viewport-select.html"); NavigateTo(base_url_ + "viewport-select.html"); - ASSERT_EQ(2.0f, WebViewImpl()->PageScaleFactor()); - WebViewImpl()->SetInitialFocus(false); - Element* element = WebViewImpl()->FocusedElement(); + ASSERT_EQ(2.0f, WebView()->PageScaleFactor()); + WebView()->SetInitialFocus(false); + Element* element = WebView()->FocusedElement(); EXPECT_FALSE(element->VisibleBoundsInVisualViewport().IsEmpty()); - WebViewImpl()->SetPageScaleFactor(4.0); + WebView()->SetPageScaleFactor(4.0); EXPECT_TRUE(element->VisibleBoundsInVisualViewport().IsEmpty()); } @@ -1687,7 +1684,7 @@ // methods don't change with the visual viewport. TEST_P(VisualViewportTest, visualViewportIsInert) { FrameTestHelpers::WebViewHelper web_view_helper; - WebViewBase* web_view_impl = web_view_helper.Initialize( + WebViewImpl* web_view_impl = web_view_helper.Initialize( nullptr, nullptr, nullptr, &configureAndroidCompositing); web_view_impl->Resize(IntSize(200, 300)); @@ -1770,12 +1767,12 @@ TEST_P(VisualViewportTest, TestMainFrameInitializationSizing) { InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(100, 200)); + WebView()->Resize(IntSize(100, 200)); RegisterMockedHttpURLLoad("content-width-1000-min-scale.html"); NavigateTo(base_url_ + "content-width-1000-min-scale.html"); - WebLocalFrameImpl* local_frame = WebViewImpl()->MainFrameImpl(); + WebLocalFrameImpl* local_frame = WebView()->MainFrameImpl(); // The shutdown() calls are a hack to prevent this test from violating // invariants about frame state during navigation/detach. local_frame->GetFrame()->GetDocument()->Shutdown(); @@ -1789,16 +1786,16 @@ // Tests that the maximum scroll offset of the viewport can be fractional. TEST_P(VisualViewportTest, FractionalMaxScrollOffset) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(101, 201)); + WebView()->Resize(IntSize(101, 201)); NavigateTo("about:blank"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); ScrollableArea* scrollable_area = &visual_viewport; - WebViewImpl()->SetPageScaleFactor(1.0); + WebView()->SetPageScaleFactor(1.0); EXPECT_SIZE_EQ(ScrollOffset(), scrollable_area->MaximumScrollOffset()); - WebViewImpl()->SetPageScaleFactor(2); + WebView()->SetPageScaleFactor(2); EXPECT_SIZE_EQ(ScrollOffset(101. / 2., 201. / 2.), scrollable_area->MaximumScrollOffset()); } @@ -1808,14 +1805,14 @@ // ScrollAnimatorBase class. TEST_P(VisualViewportTest, SlowScrollAfterImplScroll) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(800, 600)); + WebView()->Resize(IntSize(800, 600)); NavigateTo("about:blank"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); // Apply some scroll and scale from the impl-side. - WebViewImpl()->ApplyViewportDeltas(WebFloatSize(300, 200), WebFloatSize(0, 0), - WebFloatSize(0, 0), 2, 0); + WebView()->ApplyViewportDeltas(WebFloatSize(300, 200), WebFloatSize(0, 0), + WebFloatSize(0, 0), 2, 0); EXPECT_SIZE_EQ(FloatSize(300, 200), visual_viewport.GetScrollOffset()); @@ -1858,14 +1855,14 @@ RegisterMockedHttpURLLoad("hit-test.html"); NavigateTo(base_url_ + "hit-test.html"); - WebViewImpl()->Resize(IntSize(500, 500)); - WebViewImpl()->UpdateAllLifecyclePhases(); + WebView()->Resize(IntSize(500, 500)); + WebView()->UpdateAllLifecyclePhases(); - WebDocument web_doc = WebViewImpl()->MainFrameImpl()->GetDocument(); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + WebDocument web_doc = WebView()->MainFrameImpl()->GetDocument(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); - WebViewImpl()->SetPageScaleFactor(2); - WebViewImpl()->SetVisualViewportOffset(WebFloatPoint(200, 230)); + WebView()->SetPageScaleFactor(2); + WebView()->SetVisualViewportOffset(WebFloatPoint(200, 230)); frame_view.LayoutViewportScrollableArea()->SetScrollOffset( ScrollOffset(400, 1100), kProgrammaticScroll); @@ -1885,13 +1882,12 @@ // Tests that the maximum scroll offset of the viewport can be fractional. TEST_P(VisualViewportTest, TestCoordinateTransforms) { InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(800, 600)); + WebView()->Resize(IntSize(800, 600)); RegisterMockedHttpURLLoad("content-width-1000.html"); NavigateTo(base_url_ + "content-width-1000.html"); - VisualViewport& visual_viewport = - WebViewImpl()->GetPage()->GetVisualViewport(); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + VisualViewport& visual_viewport = WebView()->GetPage()->GetVisualViewport(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); // At scale = 1 the transform should be a no-op. visual_viewport.SetScale(1); @@ -1943,7 +1939,7 @@ TEST_P(VisualViewportTest, WindowDimensionsOnLoad) { InitializeWithAndroidSettings(); RegisterMockedHttpURLLoad("window_dimensions.html"); - WebViewImpl()->Resize(IntSize(800, 600)); + WebView()->Resize(IntSize(800, 600)); NavigateTo(base_url_ + "window_dimensions.html"); Element* output = GetFrame()->GetDocument()->getElementById("output"); @@ -1959,7 +1955,7 @@ TEST_P(VisualViewportTest, WindowDimensionsOnLoadWideContent) { InitializeWithAndroidSettings(); RegisterMockedHttpURLLoad("window_dimensions_wide_div.html"); - WebViewImpl()->Resize(IntSize(800, 600)); + WebView()->Resize(IntSize(800, 600)); NavigateTo(base_url_ + "window_dimensions_wide_div.html"); Element* output = GetFrame()->GetDocument()->getElementById("output"); @@ -1970,7 +1966,7 @@ TEST_P(VisualViewportTest, PinchZoomGestureScrollsVisualViewportOnly) { InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(100, 100)); + WebView()->Resize(IntSize(100, 100)); RegisterMockedHttpURLLoad("200-by-800-viewport.html"); NavigateTo(base_url_ + "200-by-800-viewport.html"); @@ -1984,11 +1980,10 @@ pinch_update.data.pinch_update.scale = 2; pinch_update.data.pinch_update.zoom_disabled = false; - WebViewImpl()->HandleInputEvent(WebCoalescedInputEvent(pinch_update)); + WebView()->HandleInputEvent(WebCoalescedInputEvent(pinch_update)); - VisualViewport& visual_viewport = - WebViewImpl()->GetPage()->GetVisualViewport(); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + VisualViewport& visual_viewport = WebView()->GetPage()->GetVisualViewport(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); EXPECT_FLOAT_SIZE_EQ(FloatSize(50, 50), visual_viewport.GetScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 0), @@ -2001,17 +1996,17 @@ RuntimeEnabledFeatures::SetScrollAnchoringEnabled(true); InitializeWithDesktopSettings(); - WebViewImpl()->Resize(IntSize(800, 600)); + WebView()->Resize(IntSize(800, 600)); RegisterMockedHttpURLLoad("icb-relative-content.html"); NavigateTo(base_url_ + "icb-relative-content.html"); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); frame_view.LayoutViewportScrollableArea()->SetScrollOffset( ScrollOffset(700, 500), kProgrammaticScroll); - WebViewImpl()->UpdateAllLifecyclePhases(); + WebView()->UpdateAllLifecyclePhases(); - WebViewImpl()->Resize(IntSize(800, 300)); + WebView()->Resize(IntSize(800, 300)); EXPECT_SIZE_EQ(ScrollOffset(700, 200), frame_view.LayoutViewportScrollableArea()->GetScrollOffset()); @@ -2026,26 +2021,25 @@ RuntimeEnabledFeatures::SetSetRootScrollerEnabled(true); InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(800, 600)); + WebView()->Resize(IntSize(800, 600)); RegisterMockedHttpURLLoad("root-scroller-div.html"); NavigateTo(base_url_ + "root-scroller-div.html"); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); Element* scroller = GetFrame()->GetDocument()->getElementById("rootScroller"); NonThrowableExceptionState non_throw; GetFrame()->GetDocument()->setRootScroller(scroller, non_throw); - WebViewImpl()->SetPageScaleFactor(3.f); + WebView()->SetPageScaleFactor(3.f); frame_view.GetScrollableArea()->SetScrollOffset(ScrollOffset(0, 400), kProgrammaticScroll); - VisualViewport& visual_viewport = - WebViewImpl()->GetPage()->GetVisualViewport(); + VisualViewport& visual_viewport = WebView()->GetPage()->GetVisualViewport(); visual_viewport.SetScrollOffset(ScrollOffset(0, 400), kProgrammaticScroll); - WebViewImpl()->Resize(IntSize(800, 500)); + WebView()->Resize(IntSize(800, 500)); EXPECT_SIZE_EQ(ScrollOffset(), frame_view.LayoutViewportScrollableArea()->GetScrollOffset()); @@ -2061,21 +2055,21 @@ RuntimeEnabledFeatures::SetSetRootScrollerEnabled(true); InitializeWithAndroidSettings(); - WebViewImpl()->Resize(IntSize(800, 600)); + WebView()->Resize(IntSize(800, 600)); RegisterMockedHttpURLLoad("root-scroller-div.html"); NavigateTo(base_url_ + "root-scroller-div.html"); - LocalFrameView& frame_view = *WebViewImpl()->MainFrameImpl()->GetFrameView(); + LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); Element* scroller = GetFrame()->GetDocument()->getElementById("rootScroller"); NonThrowableExceptionState non_throw; GetFrame()->GetDocument()->setRootScroller(scroller, non_throw); - WebViewImpl()->UpdateAllLifecyclePhases(); + WebView()->UpdateAllLifecyclePhases(); scroller->setScrollTop(800); - WebViewImpl()->Resize(IntSize(600, 800)); + WebView()->Resize(IntSize(600, 800)); EXPECT_SIZE_EQ(ScrollOffset(), frame_view.LayoutViewportScrollableArea()->GetScrollOffset()); @@ -2088,7 +2082,7 @@ // when using inert (non-layout affecting) browser controls. TEST_P(VisualViewportTest, ResizeCompositedAndFixedBackground) { FrameTestHelpers::WebViewHelper web_view_helper; - WebViewBase* web_view_impl = web_view_helper.Initialize( + WebViewImpl* web_view_impl = web_view_helper.Initialize( nullptr, nullptr, nullptr, &configureAndroidCompositing); int page_width = 640; @@ -2170,7 +2164,7 @@ // resized when using inert (non-layout affecting) browser controls. TEST_P(VisualViewportTest, ResizeNonCompositedAndFixedBackground) { FrameTestHelpers::WebViewHelper web_view_helper; - WebViewBase* web_view_impl = web_view_helper.Initialize( + WebViewImpl* web_view_impl = web_view_helper.Initialize( nullptr, nullptr, nullptr, &configureAndroidNonCompositing); int page_width = 640; @@ -2268,7 +2262,7 @@ // background doesn't cause invalidation or layout. TEST_P(VisualViewportTest, ResizeNonFixedBackgroundNoLayoutOrInvalidation) { FrameTestHelpers::WebViewHelper web_view_helper; - WebViewBase* web_view_impl = web_view_helper.Initialize( + WebViewImpl* web_view_impl = web_view_helper.Initialize( nullptr, nullptr, nullptr, &configureAndroidCompositing); int page_width = 640; @@ -2343,7 +2337,7 @@ TEST_P(VisualViewportTest, InvalidateLayoutViewWhenDocumentSmallerThanView) { FrameTestHelpers::WebViewHelper web_view_helper; - WebViewBase* web_view_impl = web_view_helper.Initialize( + WebViewImpl* web_view_impl = web_view_helper.Initialize( nullptr, nullptr, nullptr, &configureAndroidCompositing); int page_width = 320; @@ -2391,10 +2385,10 @@ // it doesn't crash. TEST_P(VisualViewportTest, AutoResizeNoHeightUsesMinimumHeight) { InitializeWithDesktopSettings(); - WebViewImpl()->ResizeWithBrowserControls(WebSize(0, 0), 0, 0, false); - WebViewImpl()->EnableAutoResizeMode(WebSize(25, 25), WebSize(100, 100)); + WebView()->ResizeWithBrowserControls(WebSize(0, 0), 0, 0, false); + WebView()->EnableAutoResizeMode(WebSize(25, 25), WebSize(100, 100)); WebURL base_url = URLTestHelpers::ToKURL("http://example.com/"); - FrameTestHelpers::LoadHTMLString(WebViewImpl()->MainFrameImpl(), + FrameTestHelpers::LoadHTMLString(WebView()->MainFrameImpl(), "<!DOCTYPE html>" "<style>" " body {"
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameBase.h b/third_party/WebKit/Source/core/frame/WebLocalFrameBase.h deleted file mode 100644 index 16f1047..0000000 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameBase.h +++ /dev/null
@@ -1,92 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file.#ifndef WebViewBase_h - -#ifndef WebLocalFrameBase_h -#define WebLocalFrameBase_h - -#include "core/CoreExport.h" -#include "core/frame/WebFrameWidgetBase.h" -#include "core/loader/FrameLoaderTypes.h" -#include "public/web/WebLocalFrame.h" - -namespace blink { - -class ContentSettingsClient; -class FrameOwner; -class LocalFrame; -class LocalFrameView; -class Node; -class Page; -class SharedWorkerRepositoryClientImpl; -class TextCheckerClient; -class TextFinder; -class WebDevToolsAgentImpl; -class WebDevToolsFrontendImpl; -class WebFrameClient; -class WebFrameWidgetBase; -class WebTextCheckClient; -class WebViewBase; - -// WebLocalFrameBase is a temporary class the provides a layer of abstraction -// for WebLocalFrameImpl. Mehtods that are declared public in WebLocalFrameImpl -// that are not overrides from WebLocalFrame will be declared pure virtual in -// WebLocalFrameBase. Classes that then have a dependency on WebLocalFrameImpl -// will then take a dependency on WebLocalFrameBase instead, so we can remove -// cyclic dependencies in web/ and move classes from web/ into core/ or -// modules. -// TODO(slangley): Remove this class once WebLocalFrameImpl is in core/. -class WebLocalFrameBase : public GarbageCollectedFinalized<WebLocalFrameBase>, - public WebLocalFrame { - public: - virtual WebViewBase* ViewImpl() const = 0; - virtual WebFrameClient* Client() const = 0; - virtual void SetClient(WebFrameClient*) = 0; - virtual WebTextCheckClient* TextCheckClient() const = 0; - virtual void SetContextMenuNode(Node*) = 0; - virtual void ClearContextMenuNode() = 0; - virtual LocalFrame* GetFrame() const = 0; - virtual LocalFrameView* GetFrameView() const = 0; - virtual void InitializeCoreFrame(Page&, - FrameOwner*, - const AtomicString& name) = 0; - virtual TextFinder& EnsureTextFinder() = 0; - virtual WebFrameWidgetBase* FrameWidget() const = 0; - virtual void SetFrameWidget(WebFrameWidgetBase*) = 0; - virtual WebDevToolsAgentImpl* DevToolsAgentImpl() const = 0; - virtual void SetDevToolsFrontend(WebDevToolsFrontendImpl*) = 0; - virtual WebDevToolsFrontendImpl* DevToolsFrontend() = 0; - virtual void WillBeDetached() = 0; - virtual void WillDetachParent() = 0; - virtual void SetCoreFrame(LocalFrame*) = 0; - virtual void DidFail(const ResourceError&, - bool was_provisional, - HistoryCommitType) = 0; - virtual void DidFinish() = 0; - virtual void CreateFrameView() = 0; - virtual LocalFrame* CreateChildFrame(const AtomicString& name, - HTMLFrameOwnerElement*) = 0; - virtual ContentSettingsClient& GetContentSettingsClient() = 0; - virtual SharedWorkerRepositoryClientImpl* SharedWorkerRepositoryClient() - const = 0; - virtual TextCheckerClient& GetTextCheckerClient() const = 0; - virtual TextFinder* GetTextFinder() const = 0; - virtual void SetInputEventsScaleForEmulation(float) = 0; - - virtual WebFrameWidgetBase* LocalRootFrameWidget() = 0; - - DEFINE_INLINE_VIRTUAL_TRACE() {} - - protected: - explicit WebLocalFrameBase(WebTreeScopeType scope) : WebLocalFrame(scope) {} -}; - -DEFINE_TYPE_CASTS(WebLocalFrameBase, - WebFrame, - frame, - frame->IsWebLocalFrame(), - frame.IsWebLocalFrame()); - -} // namespace blink - -#endif // WebLocalFrameBase_h
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp index bd46b9d5..82a1591 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -1598,7 +1598,7 @@ WebTreeScopeType scope, WebFrameClient* client, blink::InterfaceRegistry* interface_registry) - : WebLocalFrameBase(scope), + : WebLocalFrame(scope), local_frame_client_(LocalFrameClientImpl::Create(this)), client_(client), autofill_client_(0), @@ -1640,8 +1640,6 @@ visitor->Trace(context_menu_node_); visitor->Trace(input_method_controller_); visitor->Trace(text_checker_client_); - WebLocalFrameBase::Trace(visitor); - // TODO(slangley): Call this from WebLocalFrameBase, once WebFrame is in core. WebFrame::TraceFrames(visitor, this); }
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h index 7f7398d4..0df14dd3 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.h
@@ -37,7 +37,6 @@ #include "core/frame/ContentSettingsClient.h" #include "core/frame/LocalFrame.h" #include "core/frame/WebFrameWidgetBase.h" -#include "core/frame/WebLocalFrameBase.h" #include "platform/WebTaskRunner.h" #include "platform/geometry/FloatRect.h" #include "platform/heap/SelfKeepAlive.h" @@ -82,7 +81,8 @@ // Implementation of WebFrame, note that this is a reference counted object. class CORE_EXPORT WebLocalFrameImpl final - : NON_EXPORTED_BASE(public WebLocalFrameBase) { + : public NON_EXPORTED_BASE(GarbageCollectedFinalized<WebLocalFrameImpl>), + public NON_EXPORTED_BASE(WebLocalFrame) { public: // WebFrame methods: // TODO(dcheng): Fix sorting here; a number of method have been moved to @@ -324,13 +324,11 @@ void AdvanceFocusInForm(WebFocusType) override; - void InitializeCoreFrame(Page&, - FrameOwner*, - const AtomicString& name) override; - LocalFrame* GetFrame() const override { return frame_.Get(); } + void InitializeCoreFrame(Page&, FrameOwner*, const AtomicString& name); + LocalFrame* GetFrame() const { return frame_.Get(); } - void WillBeDetached() override; - void WillDetachParent() override; + void WillBeDetached(); + void WillDetachParent(); static WebLocalFrameImpl* Create(WebTreeScopeType, WebFrameClient*, @@ -351,23 +349,23 @@ ~WebLocalFrameImpl() override; LocalFrame* CreateChildFrame(const AtomicString& name, - HTMLFrameOwnerElement*) override; + HTMLFrameOwnerElement*); void DidChangeContentsSize(const IntSize&); - void CreateFrameView() override; + void CreateFrameView(); static WebLocalFrameImpl* FromFrame(LocalFrame*); static WebLocalFrameImpl* FromFrame(LocalFrame&); static WebLocalFrameImpl* FromFrameOwnerElement(Element*); - WebViewBase* ViewImpl() const override; + WebViewBase* ViewImpl() const; - LocalFrameView* GetFrameView() const override { + LocalFrameView* GetFrameView() const { return GetFrame() ? GetFrame()->View() : 0; } - WebDevToolsAgentImpl* DevToolsAgentImpl() const override { + WebDevToolsAgentImpl* DevToolsAgentImpl() const { return dev_tools_agent_.Get(); } @@ -379,71 +377,66 @@ // allows us to navigate by pressing Enter after closing the Find box. void SetFindEndstateFocusAndSelection(); - void DidFail(const ResourceError&, - bool was_provisional, - HistoryCommitType) override; - void DidFinish() override; + void DidFail(const ResourceError&, bool was_provisional, HistoryCommitType); + void DidFinish(); // Sets whether the WebLocalFrameImpl allows its document to be scrolled. // If the parameter is true, allow the document to be scrolled. // Otherwise, disallow scrolling. void SetCanHaveScrollbars(bool) override; - WebFrameClient* Client() const override { return client_; } - void SetClient(WebFrameClient* client) override { client_ = client; } + WebFrameClient* Client() const { return client_; } + void SetClient(WebFrameClient* client) { client_ = client; } - ContentSettingsClient& GetContentSettingsClient() override { + ContentSettingsClient& GetContentSettingsClient() { return content_settings_client_; }; - SharedWorkerRepositoryClientImpl* SharedWorkerRepositoryClient() - const override { + SharedWorkerRepositoryClientImpl* SharedWorkerRepositoryClient() const { return shared_worker_repository_client_.get(); } - void SetInputEventsScaleForEmulation(float) override; + void SetInputEventsScaleForEmulation(float); static void SelectWordAroundPosition(LocalFrame*, VisiblePosition); - TextCheckerClient& GetTextCheckerClient() const override; - WebTextCheckClient* TextCheckClient() const override { - return text_check_client_; - } + TextCheckerClient& GetTextCheckerClient() const; + WebTextCheckClient* TextCheckClient() const { return text_check_client_; } WebSpellCheckPanelHostClient* SpellCheckPanelHostClient() const override { return spell_check_panel_host_client_; } - TextFinder* GetTextFinder() const override; + TextFinder* GetTextFinder() const; // Returns the text finder object if it already exists. // Otherwise creates it and then returns. - TextFinder& EnsureTextFinder() override; + TextFinder& EnsureTextFinder(); // Returns a hit-tested VisiblePosition for the given point VisiblePosition VisiblePositionForViewportPoint(const WebPoint&); - void SetFrameWidget(WebFrameWidgetBase*) override; + void SetFrameWidget(WebFrameWidgetBase*); // DevTools front-end bindings. - void SetDevToolsFrontend(WebDevToolsFrontendImpl* frontend) override { + void SetDevToolsFrontend(WebDevToolsFrontendImpl* frontend) { web_dev_tools_frontend_ = frontend; } - WebDevToolsFrontendImpl* DevToolsFrontend() override { + WebDevToolsFrontendImpl* DevToolsFrontend() { return web_dev_tools_frontend_; } WebNode ContextMenuNode() const { return context_menu_node_.Get(); } - void SetContextMenuNode(Node* node) override { context_menu_node_ = node; } - void ClearContextMenuNode() override { context_menu_node_.Clear(); } + void SetContextMenuNode(Node* node) { context_menu_node_ = node; } + void ClearContextMenuNode() { context_menu_node_.Clear(); } std::unique_ptr<WebURLLoader> CreateURLLoader( const WebURLRequest&, SingleThreadTaskRunner*) override; - WebFrameWidgetBase* LocalRootFrameWidget() override; + WebFrameWidgetBase* LocalRootFrameWidget(); // Sets the local core frame and registers destruction observers. - void SetCoreFrame(LocalFrame*) override; + void SetCoreFrame(LocalFrame*); DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/html/HTMLOptionsCollection.idl b/third_party/WebKit/Source/core/html/HTMLOptionsCollection.idl index 939d491..bbbd08c 100644 --- a/third_party/WebKit/Source/core/html/HTMLOptionsCollection.idl +++ b/third_party/WebKit/Source/core/html/HTMLOptionsCollection.idl
@@ -31,8 +31,13 @@ [CEReactions, RaisesException] void add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null); [CEReactions] void remove(long index); attribute long selectedIndex; - // FIXME: Neither of these getters are in the spec, and the - // getters inherited from HTMLCollection always return an Element. + + // TODO(tkent): We need to declare this indexed property getter because our + // IDL compiler doesn't support inheritance of indexed property + // getters. crbug.com/752877 + // TODO(tkent): This getter should return Element. [ImplementedAs=item] getter Node (unsigned long index); + + // TODO(tkent): This should return only Element. crbug.com/695902 [ImplementedAs=namedGetter] getter (NodeList or Element)? namedItem(DOMString name); };
diff --git a/third_party/WebKit/Source/core/html/RadioNodeList.idl b/third_party/WebKit/Source/core/html/RadioNodeList.idl index 148d563..9cd41f6b 100644 --- a/third_party/WebKit/Source/core/html/RadioNodeList.idl +++ b/third_party/WebKit/Source/core/html/RadioNodeList.idl
@@ -28,6 +28,8 @@ interface RadioNodeList : NodeList { attribute DOMString value; - // TODO(foolip): This should be inherited from NodeList. + // TODO(tkent): We need to declare this indexed property getter because our + // IDL compiler doesn't support inheritance of indexed property + // getters. crbug.com/752877 [ImplementedAs=item] getter Node? (unsigned long index); };
diff --git a/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp b/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp index a0829a0f..615a1bc 100644 --- a/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp +++ b/third_party/WebKit/Source/core/html/forms/InternalPopupMenu.cpp
@@ -12,7 +12,7 @@ #include "core/dom/StyleEngine.h" #include "core/dom/TaskRunnerHelper.h" #include "core/events/ScopedEventQueue.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrame.h" #include "core/frame/LocalFrameView.h" #include "core/html/HTMLHRElement.h"
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp index 6729422f..94c469b 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp
@@ -242,7 +242,12 @@ request->SetNonce(nonce_); request->SetCharset(Charset()); request->SetDefer(defer_); - request->SetIntegrityMetadata(integrity_metadata_); + + // The only link tags that should keep the integrity metadata are + // stylesheets until crbug.com/677022 is resolved. + if (link_is_style_sheet_ || !Match(tag_impl_, linkTag)) + request->SetIntegrityMetadata(integrity_metadata_); + if (scanner_type_ == ScannerType::kInsertion) request->SetFromInsertionScanner(true); @@ -264,12 +269,6 @@ SetDefer(FetchParameters::kLazyLoad); else if (Match(attribute_name, deferAttr)) SetDefer(FetchParameters::kLazyLoad); - // Note that only scripts need to have the integrity metadata set on - // preloads. This is because script resources fetches, and only script - // resource fetches, need to re-request resources if a cached version has - // different metadata (including empty) from the metadata on the request. - // See the comment before the call to mustRefetchDueToIntegrityMismatch() in - // Source/core/fetch/ResourceFetcher.cpp for a more complete explanation. else if (Match(attribute_name, integrityAttr)) SubresourceIntegrity::ParseIntegrityAttribute(attribute_value, integrity_metadata_); @@ -355,6 +354,9 @@ SecurityPolicy::ReferrerPolicyFromString( attribute_value, kDoNotSupportReferrerPolicyLegacyKeywords, &referrer_policy_); + } else if (Match(attribute_name, integrityAttr)) { + SubresourceIntegrity::ParseIntegrityAttribute(attribute_value, + integrity_metadata_); } }
diff --git a/third_party/WebKit/Source/core/html/parser/PreloadRequest.h b/third_party/WebKit/Source/core/html/parser/PreloadRequest.h index 8bbe73a8..91f02caa 100644 --- a/third_party/WebKit/Source/core/html/parser/PreloadRequest.h +++ b/third_party/WebKit/Source/core/html/parser/PreloadRequest.h
@@ -94,12 +94,14 @@ return client_hints_preferences_; } ReferrerPolicy GetReferrerPolicy() const { return referrer_policy_; } + + // Only scripts and css stylesheets need to have integrity set on preloads. + // This is because neither resource keeps raw data around to redo an + // integrity check. A resource in memory cache needs integrity + // data cached to match an outgoing request. void SetIntegrityMetadata(const IntegrityMetadataSet& metadata_set) { integrity_metadata_ = metadata_set; } - const IntegrityMetadataSet& IntegrityMetadata() const { - return integrity_metadata_; - } void SetFromInsertionScanner(const bool from_insertion_scanner) { from_insertion_scanner_ = from_insertion_scanner; }
diff --git a/third_party/WebKit/Source/core/inspector/DevToolsEmulator.cpp b/third_party/WebKit/Source/core/inspector/DevToolsEmulator.cpp index c9f38134..888aac3 100644 --- a/third_party/WebKit/Source/core/inspector/DevToolsEmulator.cpp +++ b/third_party/WebKit/Source/core/inspector/DevToolsEmulator.cpp
@@ -94,7 +94,6 @@ .GetMainFrameResizesAreOrientationChanges()), touch_event_emulation_enabled_(false), double_tap_to_zoom_enabled_(false), - original_touch_event_feature_detection_enabled_(false), original_device_supports_touch_(false), original_max_touch_points_(0), embedder_script_enabled_( @@ -477,15 +476,14 @@ if (touch_event_emulation_enabled_ == enabled) return; if (!touch_event_emulation_enabled_) { - original_touch_event_feature_detection_enabled_ = - RuntimeEnabledFeatures::TouchEventFeatureDetectionEnabled(); original_device_supports_touch_ = web_view_->GetPage()->GetSettings().GetDeviceSupportsTouch(); original_max_touch_points_ = web_view_->GetPage()->GetSettings().GetMaxTouchPoints(); } - RuntimeEnabledFeatures::SetTouchEventFeatureDetectionEnabled( - enabled ? true : original_touch_event_feature_detection_enabled_); + web_view_->GetPage() + ->GetSettings() + .SetForceTouchEventFeatureDetectionForInspector(enabled); if (!original_device_supports_touch_) { if (enabled && web_view_->MainFrameImpl()) { web_view_->MainFrameImpl()
diff --git a/third_party/WebKit/Source/core/inspector/DevToolsEmulator.h b/third_party/WebKit/Source/core/inspector/DevToolsEmulator.h index f7120a0..f4bdd471 100644 --- a/third_party/WebKit/Source/core/inspector/DevToolsEmulator.h +++ b/third_party/WebKit/Source/core/inspector/DevToolsEmulator.h
@@ -109,7 +109,6 @@ bool touch_event_emulation_enabled_; bool double_tap_to_zoom_enabled_; - bool original_touch_event_feature_detection_enabled_; bool original_device_supports_touch_; int original_max_touch_points_; std::unique_ptr<IntPoint> last_pinch_anchor_css_;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorOverlayAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorOverlayAgent.cpp index e73e5b54..45b606c 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorOverlayAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorOverlayAgent.cpp
@@ -41,7 +41,7 @@ #include "core/dom/StaticNodeList.h" #include "core/dom/TaskRunnerHelper.h" #include "core/events/WebInputEventConversion.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrame.h" #include "core/frame/LocalFrameClient.h" #include "core/frame/LocalFrameView.h"
diff --git a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserverTest.cpp b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserverTest.cpp index 85ca7374..0da2358 100644 --- a/third_party/WebKit/Source/core/intersection_observer/IntersectionObserverTest.cpp +++ b/third_party/WebKit/Source/core/intersection_observer/IntersectionObserverTest.cpp
@@ -4,7 +4,7 @@ #include "core/intersection_observer/IntersectionObserver.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrameView.h" #include "core/intersection_observer/IntersectionObserverDelegate.h" #include "core/intersection_observer/IntersectionObserverInit.h"
diff --git a/third_party/WebKit/Source/core/layout/ng/NGInlineLayoutTest.cpp b/third_party/WebKit/Source/core/layout/ng/NGInlineLayoutTest.cpp index bdf5f18d..934f151 100644 --- a/third_party/WebKit/Source/core/layout/ng/NGInlineLayoutTest.cpp +++ b/third_party/WebKit/Source/core/layout/ng/NGInlineLayoutTest.cpp
@@ -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 "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/layout/ng/inline/ng_inline_node.h" #include "core/layout/ng/layout_ng_block_flow.h" #include "core/layout/ng/ng_block_layout_algorithm.h"
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc index f0df9dc..81df3cb8 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -282,7 +282,8 @@ input_bfc_block_offset += content_size_; NGPreviousInflowPosition previous_inflow_position = { - input_bfc_block_offset, content_size_, input_margin_strut}; + input_bfc_block_offset, content_size_, input_margin_strut, + /* empty_block_affected_by_clearance */ false}; NGBlockChildIterator child_iterator(Node().FirstChild(), BreakToken()); for (auto entry = child_iterator.NextChild(); @@ -311,11 +312,14 @@ NGMarginStrut end_margin_strut = previous_inflow_position.margin_strut; LayoutUnit end_bfc_block_offset = previous_inflow_position.bfc_block_offset; - // Margins collapsing: - // Bottom margins of an in-flow block box doesn't collapse with its last - // in-flow block-level child's bottom margin if the box has bottom - // border/padding. + // The end margin strut of an in-flow fragment contributes to the size of the + // current fragment if: + // - There is block-end border/scrollbar/padding. + // - There was empty block(s) affected by clearance. + // - We are a new formatting context. + // Additionally this fragment produces no end margin strut. if (border_scrollbar_padding_.block_end || + previous_inflow_position.empty_block_affected_by_clearance || ConstraintSpace().IsNewFormattingContext()) { // TODO(ikilpatrick): If we are a quirky container and our last child had a // quirky block end margin, we need to use the margin strut without the @@ -348,6 +352,7 @@ // Non-empty blocks always know their position in space. // TODO(ikilpatrick): This check for a break token seems error prone. if (size.block_size || BreakToken()) { + // TODO(ikilpatrick): This looks wrong with end_margin_strut above? end_bfc_block_offset += end_margin_strut.Sum(); bool updated = MaybeUpdateFragmentBfcOffset( ConstraintSpace(), end_bfc_block_offset, &container_builder_); @@ -593,14 +598,16 @@ NGLogicalOffset logical_offset = CalculateLogicalOffset(child_data.margins, child_bfc_offset); - // Only modify content_size_ if the fragment is not an empty block. This is - // needed to prevent the situation when logical_offset is included in - // content_size_ for empty blocks. Example: - // <div style="overflow:hidden"> - // <div style="margin-top: 8px"></div> - // <div style="margin-top: 10px"></div> - // </div> + // Only modify content_size_ if the fragment is non-empty block. + // + // Empty blocks don't immediately contribute to our size, instead we wait to + // see what the final margin produced, e.g. + // <div style="display: flow-root"> + // <div style="margin-top: -8px"></div> + // <div style="margin-top: 10px"></div> + // </div> if (!IsEmptyBlock(child, *layout_result)) { + DCHECK(container_builder_.BfcOffset()); content_size_ = std::max( content_size_, logical_offset.block_offset + fragment.BlockSize()); } @@ -655,7 +662,8 @@ LayoutUnit child_end_bfc_block_offset; LayoutUnit logical_block_offset; - if (IsEmptyBlock(child, layout_result)) { + bool is_empty_block = IsEmptyBlock(child, layout_result); + if (is_empty_block) { if (empty_block_affected_by_clearance) { // If an empty block was affected by clearance (that is it got pushed // down past a float), we need to do something slightly bizarre. @@ -694,7 +702,23 @@ margin_strut.Append(child_data.margins.block_end, child.Style().HasMarginAfterQuirk()); - return {child_end_bfc_block_offset, logical_block_offset, margin_strut}; + // This flag is subtle, but in order to determine our size correctly we need + // to check if our last child is an empty block, and it was affected by + // clearance *or* an adjoining empty sibling was affected by clearance. E.g. + // <div id="container"> + // <div id="float"></div> + // <div id="zero-with-clearance"></div> + // <div id="another-zero"></div> + // </div> + // In the above case #container's size will depend on the end margin strut of + // #another-zero, even though usually it wouldn't. + bool empty_or_sibling_empty_affected_by_clearance = + empty_block_affected_by_clearance || + (previous_inflow_position.empty_block_affected_by_clearance && + is_empty_block); + + return {child_end_bfc_block_offset, logical_block_offset, margin_strut, + empty_or_sibling_empty_affected_by_clearance}; } bool NGBlockLayoutAlgorithm::PositionNewFc(
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h index 76556c06..fa2fc79 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
@@ -25,6 +25,7 @@ LayoutUnit bfc_block_offset; LayoutUnit logical_block_offset; NGMarginStrut margin_strut; + bool empty_block_affected_by_clearance; }; // This strut holds information for the current inflow child. The data is not
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp index a11d114..f4710b5 100644 --- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp +++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -946,6 +946,10 @@ document->SetContentLanguage(AtomicString(header_content_language)); } + if (settings->GetForceTouchEventFeatureDetectionForInspector()) { + OriginTrialContext::From(document)->AddFeature( + "ForceTouchEventFeatureDetectionForInspector"); + } OriginTrialContext::AddTokensFromHeader( document, response_.HttpHeaderField(HTTPNames::Origin_Trial)); String referrer_policy_header =
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoaderTest.cpp b/third_party/WebKit/Source/core/loader/DocumentLoaderTest.cpp index 23dba88..b86f200 100644 --- a/third_party/WebKit/Source/core/loader/DocumentLoaderTest.cpp +++ b/third_party/WebKit/Source/core/loader/DocumentLoaderTest.cpp
@@ -185,7 +185,7 @@ } TEST_F(DocumentLoaderTest, isCommittedButEmpty) { - WebViewBase* web_view_impl = + WebViewImpl* web_view_impl = web_view_helper_.InitializeAndLoad("about:blank"); EXPECT_TRUE(ToLocalFrame(web_view_impl->GetPage()->MainFrame()) ->Loader()
diff --git a/third_party/WebKit/Source/core/loader/PrerendererClient.cpp b/third_party/WebKit/Source/core/loader/PrerendererClient.cpp index ebad4c77..9516c18 100644 --- a/third_party/WebKit/Source/core/loader/PrerendererClient.cpp +++ b/third_party/WebKit/Source/core/loader/PrerendererClient.cpp
@@ -31,7 +31,7 @@ #include "core/loader/PrerendererClient.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/page/Page.h" #include "platform/Prerender.h" #include "public/platform/WebPrerender.h"
diff --git a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp index 29bafaf..b88b02d 100644 --- a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp +++ b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp
@@ -204,6 +204,11 @@ } } +void OriginTrialContext::AddFeature(const String& feature) { + enabled_trials_.insert(feature); + InitializePendingFeatures(); +} + bool OriginTrialContext::IsTrialEnabled(const String& trial_name) { if (!RuntimeEnabledFeatures::OriginTrialsEnabled()) return false;
diff --git a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h index e1024be..1d4e15d5 100644 --- a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h +++ b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.h
@@ -68,6 +68,10 @@ void AddToken(const String& token); void AddTokens(const Vector<String>& tokens); + // Forces a given origin-trial-enabled feature to be enabled in this context + // and immediately adds required bindings to already initialized JS contexts. + void AddFeature(const String& feature); + // Returns true if the trial (and therefore the feature or features it // controls) should be considered enabled for the current execution context. bool IsTrialEnabled(const String& trial_name);
diff --git a/third_party/WebKit/Source/core/page/ChromeClientImplTest.cpp b/third_party/WebKit/Source/core/page/ChromeClientImplTest.cpp index b4aa10a..36c741a 100644 --- a/third_party/WebKit/Source/core/page/ChromeClientImplTest.cpp +++ b/third_party/WebKit/Source/core/page/ChromeClientImplTest.cpp
@@ -28,7 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/FrameTestHelpers.h" #include "core/frame/WebLocalFrameImpl.h" #include "core/html/HTMLSelectElement.h" @@ -91,7 +91,7 @@ ViewCreatingClient web_view_client_; FrameTestHelpers::WebViewHelper helper_; - WebViewBase* web_view_; + WebViewImpl* web_view_; WebLocalFrame* main_frame_; Persistent<ChromeClientImpl> chrome_client_impl_; }; @@ -205,7 +205,7 @@ protected: FrameTestHelpers::WebViewHelper helper_; - WebViewBase* web_view_; + WebViewImpl* web_view_; Persistent<WebLocalFrameImpl> main_frame_; Persistent<ChromeClientImpl> chrome_client_impl_; Persistent<FakeColorChooserClient> color_chooser_client_;
diff --git a/third_party/WebKit/Source/core/page/ContextMenuClient.cpp b/third_party/WebKit/Source/core/page/ContextMenuClient.cpp index bfe4151..52e7fbe 100644 --- a/third_party/WebKit/Source/core/page/ContextMenuClient.cpp +++ b/third_party/WebKit/Source/core/page/ContextMenuClient.cpp
@@ -43,7 +43,7 @@ #include "core/editing/spellcheck/SpellChecker.h" #include "core/exported/WebDocumentLoaderImpl.h" #include "core/exported/WebPluginContainerImpl.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrameView.h" #include "core/frame/Settings.h" #include "core/frame/VisualViewport.h"
diff --git a/third_party/WebKit/Source/core/page/ContextMenuClient.h b/third_party/WebKit/Source/core/page/ContextMenuClient.h index 9f412604..297775f 100644 --- a/third_party/WebKit/Source/core/page/ContextMenuClient.h +++ b/third_party/WebKit/Source/core/page/ContextMenuClient.h
@@ -34,12 +34,12 @@ class ContextMenu; class Document; class Editor; -class WebViewBase; +class WebViewImpl; struct WebContextMenuData; class CORE_EXPORT ContextMenuClient { public: - explicit ContextMenuClient(WebViewBase& web_view) : web_view_(&web_view) {} + explicit ContextMenuClient(WebViewImpl& web_view) : web_view_(&web_view) {} virtual ~ContextMenuClient() {} // Returns whether a Context Menu was actually shown. @@ -53,7 +53,7 @@ void PopulateCustomMenuItems(const ContextMenu*, WebContextMenuData*); static int ComputeEditFlags(Document&, Editor&); bool ShouldShowContextMenuFromTouch(const blink::WebContextMenuData&); - WebViewBase* web_view_; + WebViewImpl* web_view_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/page/EditorClient.cpp b/third_party/WebKit/Source/core/page/EditorClient.cpp index 17cc5d5..a13833b 100644 --- a/third_party/WebKit/Source/core/page/EditorClient.cpp +++ b/third_party/WebKit/Source/core/page/EditorClient.cpp
@@ -27,7 +27,7 @@ #include "core/page/EditorClient.h" #include "core/editing/SelectionType.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/ContentSettingsClient.h" #include "core/frame/WebLocalFrameImpl.h" #include "public/web/WebFrameClient.h" @@ -35,7 +35,7 @@ namespace blink { -EditorClient::EditorClient(WebViewBase& webview) : web_view_(&webview) {} +EditorClient::EditorClient(WebViewImpl& webview) : web_view_(&webview) {} EditorClient::~EditorClient() {}
diff --git a/third_party/WebKit/Source/core/page/EditorClient.h b/third_party/WebKit/Source/core/page/EditorClient.h index b335fd7..fa9f6f1a 100644 --- a/third_party/WebKit/Source/core/page/EditorClient.h +++ b/third_party/WebKit/Source/core/page/EditorClient.h
@@ -34,11 +34,11 @@ namespace blink { class LocalFrame; -class WebViewBase; +class WebViewImpl; class CORE_EXPORT EditorClient { public: - explicit EditorClient(WebViewBase&); + explicit EditorClient(WebViewImpl&); virtual ~EditorClient(); virtual void RespondToChangedContents(); @@ -53,7 +53,7 @@ EditorClient(){}; private: - WebViewBase* web_view_; + WebViewImpl* web_view_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.cpp b/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.cpp index ebd4b46..244140b 100644 --- a/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.cpp +++ b/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.cpp
@@ -27,7 +27,7 @@ #include "core/dom/Element.h" #include "core/dom/TaskRunnerHelper.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrameView.h" #include "core/frame/WebLocalFrameImpl.h" #include "core/page/ChromeClient.h" @@ -42,14 +42,14 @@ namespace blink { -ValidationMessageClientImpl::ValidationMessageClientImpl(WebViewBase& web_view) +ValidationMessageClientImpl::ValidationMessageClientImpl(WebViewImpl& web_view) : web_view_(web_view), current_anchor_(nullptr), last_page_scale_factor_(1), finish_time_(0) {} ValidationMessageClientImpl* ValidationMessageClientImpl::Create( - WebViewBase& web_view) { + WebViewImpl& web_view) { return new ValidationMessageClientImpl(web_view); }
diff --git a/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.h b/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.h index 8a5a39b..ec65f0a 100644 --- a/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.h +++ b/third_party/WebKit/Source/core/page/ValidationMessageClientImpl.h
@@ -39,7 +39,7 @@ class LocalFrameView; class PageOverlay; class ValidationMessageOverlayDelegate; -class WebViewBase; +class WebViewImpl; class CORE_EXPORT ValidationMessageClientImpl final : public GarbageCollectedFinalized<ValidationMessageClientImpl>, @@ -48,13 +48,13 @@ USING_GARBAGE_COLLECTED_MIXIN(ValidationMessageClientImpl); public: - static ValidationMessageClientImpl* Create(WebViewBase&); + static ValidationMessageClientImpl* Create(WebViewImpl&); ~ValidationMessageClientImpl() override; DECLARE_VIRTUAL_TRACE(); private: - ValidationMessageClientImpl(WebViewBase&); + ValidationMessageClientImpl(WebViewImpl&); void CheckAnchorStatus(TimerBase*); LocalFrameView* CurrentView(); void HideValidationMessageImmediately(const Element& anchor); @@ -75,7 +75,7 @@ // PopupOpeningObserver function void WillOpenPopup() override; - WebViewBase& web_view_; + WebViewImpl& web_view_; Member<const Element> current_anchor_; String message_; IntRect last_anchor_rect_in_screen_;
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinatorTest.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinatorTest.cpp index 51705aa2..8142292 100644 --- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinatorTest.cpp +++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinatorTest.cpp
@@ -27,7 +27,7 @@ #include "build/build_config.h" #include "core/css/CSSStyleSheet.h" #include "core/css/StyleSheetList.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/FrameTestHelpers.h" #include "core/frame/LocalFrameView.h" #include "core/frame/VisualViewport.h" @@ -112,7 +112,7 @@ return layer ? layer->PlatformLayer() : nullptr; } - WebViewBase* GetWebView() const { return helper_.WebView(); } + WebViewImpl* GetWebView() const { return helper_.WebView(); } LocalFrame* GetFrame() const { return helper_.LocalMainFrame()->GetFrame(); } WebLayerTreeView* GetWebLayerTreeView() const {
diff --git a/third_party/WebKit/Source/core/paint/LinkHighlightImpl.cpp b/third_party/WebKit/Source/core/paint/LinkHighlightImpl.cpp index 77b4ec68..ca87f31 100644 --- a/third_party/WebKit/Source/core/paint/LinkHighlightImpl.cpp +++ b/third_party/WebKit/Source/core/paint/LinkHighlightImpl.cpp
@@ -30,7 +30,7 @@ #include "core/dom/LayoutTreeBuilderTraversal.h" #include "core/dom/Node.h" #include "core/exported/WebSettingsImpl.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrame.h" #include "core/frame/LocalFrameView.h" #include "core/frame/WebLocalFrameImpl.h" @@ -71,11 +71,11 @@ std::unique_ptr<LinkHighlightImpl> LinkHighlightImpl::Create( Node* node, - WebViewBase* owning_web_view) { + WebViewImpl* owning_web_view) { return WTF::WrapUnique(new LinkHighlightImpl(node, owning_web_view)); } -LinkHighlightImpl::LinkHighlightImpl(Node* node, WebViewBase* owning_web_view) +LinkHighlightImpl::LinkHighlightImpl(Node* node, WebViewImpl* owning_web_view) : node_(node), owning_web_view_(owning_web_view), current_graphics_layer_(0),
diff --git a/third_party/WebKit/Source/core/paint/LinkHighlightImpl.h b/third_party/WebKit/Source/core/paint/LinkHighlightImpl.h index a007315..b9a7da9 100644 --- a/third_party/WebKit/Source/core/paint/LinkHighlightImpl.h +++ b/third_party/WebKit/Source/core/paint/LinkHighlightImpl.h
@@ -45,7 +45,7 @@ class Node; class WebContentLayer; class WebLayer; -class WebViewBase; +class WebViewImpl; class CORE_EXPORT LinkHighlightImpl final : public LinkHighlight, @@ -53,7 +53,7 @@ public CompositorAnimationDelegate, public CompositorAnimationPlayerClient { public: - static std::unique_ptr<LinkHighlightImpl> Create(Node*, WebViewBase*); + static std::unique_ptr<LinkHighlightImpl> Create(Node*, WebViewImpl*); ~LinkHighlightImpl() override; WebContentLayer* ContentLayer(); @@ -84,7 +84,7 @@ } private: - LinkHighlightImpl(Node*, WebViewBase*); + LinkHighlightImpl(Node*, WebViewImpl*); void ReleaseResources(); void ComputeQuads(const Node&, Vector<FloatQuad>&) const; @@ -101,7 +101,7 @@ Path path_; Persistent<Node> node_; - WebViewBase* owning_web_view_; + WebViewImpl* owning_web_view_; GraphicsLayer* current_graphics_layer_; bool is_scrolling_graphics_layer_; std::unique_ptr<CompositorAnimationPlayer> compositor_player_;
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp index 49863e2a..3c8a7d884 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -91,27 +91,26 @@ MainThreadScrollingReasons main_thread_scrolling_reasons, WebLayerScrollClient* scroll_client) { DCHECK(!RuntimeEnabledFeatures::RootLayerScrollingEnabled()); + // TODO(pdr): Set the correct compositing reasons here. + auto element_id = CompositorElementIdFromLayoutObjectId( + frame_view.GetLayoutView()->UniqueId(), + CompositorElementIdNamespace::kScrollTranslation); if (auto* existing_scroll_translation = frame_view.ScrollTranslation()) { auto existing_reasons = existing_scroll_translation->ScrollNode() ->GetMainThreadScrollingReasons(); existing_scroll_translation->UpdateScrollTranslation( std::move(parent), matrix, origin, false, 0, kCompositingReasonNone, - CompositorElementIdFromLayoutObjectId( - frame_view.GetLayoutView()->UniqueId(), - CompositorElementIdNamespace::kScrollTranslation), - std::move(scroll_parent), clip, bounds, user_scrollable_horizontal, - user_scrollable_vertical, main_thread_scrolling_reasons, scroll_client); + std::move(scroll_parent), IntPoint(), clip, bounds, + user_scrollable_horizontal, user_scrollable_vertical, + main_thread_scrolling_reasons, element_id, scroll_client); return existing_reasons != main_thread_scrolling_reasons; } frame_view.SetScrollTranslation( TransformPaintPropertyNode::CreateScrollTranslation( std::move(parent), matrix, origin, false, 0, kCompositingReasonNone, - CompositorElementIdFromLayoutObjectId( - frame_view.GetLayoutView()->UniqueId(), - CompositorElementIdNamespace::kScrollTranslation), - std::move(scroll_parent), clip, bounds, user_scrollable_horizontal, - user_scrollable_vertical, main_thread_scrolling_reasons, - scroll_client)); + std::move(scroll_parent), IntPoint(), clip, bounds, + user_scrollable_horizontal, user_scrollable_vertical, + main_thread_scrolling_reasons, element_id, scroll_client)); return true; } @@ -966,13 +965,19 @@ const LayoutBox& box = ToLayoutBox(object); auto* scrollable_area = box.GetScrollableArea(); IntSize scroll_offset = box.ScrolledContentOffset(); + TransformationMatrix scroll_offset_matrix = + TransformationMatrix().Translate(-scroll_offset.Width(), + -scroll_offset.Height()); - auto clip_rect = box.OverflowClipRect(context.current.paint_offset); // The container bounds are snapped to integers to match the equivalent - // bounds on cc::ScrollNode. - IntSize container_bounds = PixelSnappedIntRect(clip_rect).Size(); - + // bounds on cc::ScrollNode. The offset is snapped to match the current + // integer offsets used in CompositedLayerMapping. + auto clip_rect = PixelSnappedIntRect( + box.OverflowClipRect(context.current.paint_offset)); + IntPoint bounds_offset = clip_rect.Location(); + IntSize container_bounds = clip_rect.Size(); IntSize scroll_bounds = scrollable_area->ContentsSize(); + bool user_scrollable_horizontal = scrollable_area->UserInputScrollable(kHorizontalScrollbar); bool user_scrollable_vertical = @@ -990,18 +995,17 @@ force_subtree_update = true; } - TransformationMatrix matrix = TransformationMatrix().Translate( - -scroll_offset.Width(), -scroll_offset.Height()); + auto element_id = CompositorElementIdFromLayoutObjectId( + object.UniqueId(), CompositorElementIdNamespace::kScrollTranslation); + + // TODO(pdr): Set the correct compositing reasons here. auto result = properties.UpdateScrollTranslation( - context.current.transform, matrix, FloatPoint3D(), + context.current.transform, scroll_offset_matrix, FloatPoint3D(), context.current.should_flatten_inherited_transform, context.current.rendering_context_id, kCompositingReasonNone, - CompositorElementIdFromLayoutObjectId( - object.UniqueId(), - CompositorElementIdNamespace::kScrollTranslation), - context.current.scroll, container_bounds, scroll_bounds, - user_scrollable_horizontal, user_scrollable_vertical, reasons, - scrollable_area); + context.current.scroll, bounds_offset, container_bounds, + scroll_bounds, user_scrollable_horizontal, user_scrollable_vertical, + reasons, element_id, scrollable_area); force_subtree_update |= result.NewNodeCreated(); } else { // Ensure pre-existing properties are cleared.
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp index b19d84f..ac3cd96 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -3383,15 +3383,20 @@ target->FirstFragment()->LocalBorderBoxProperties()->Effect()); } -TEST_P(PaintPropertyTreeBuilderTest, ScrollTranslationHasCompositorElementId) { +TEST_P(PaintPropertyTreeBuilderTest, ScrollNodeHasCompositorElementId) { SetBodyInnerHTML( "<div id='target' style='overflow: auto; width: 100px; height: 100px'>" " <div style='width: 200px; height: 200px'></div>" "</div>"); const ObjectPaintProperties* properties = PaintPropertiesForElement("target"); - EXPECT_NE(CompositorElementId(), + // The scroll translation node should not have the element id as it should be + // stored directly on the ScrollNode. + EXPECT_EQ(CompositorElementId(), properties->ScrollTranslation()->GetCompositorElementId()); + EXPECT_NE( + CompositorElementId(), + properties->ScrollTranslation()->ScrollNode()->GetCompositorElementId()); } TEST_P(PaintPropertyTreeBuilderTest, OverflowClipSubpixelPosition) { @@ -3650,4 +3655,58 @@ svg_root_properties->Effect()->Parent()); } +TEST_P(PaintPropertyTreeBuilderTest, ScrollBoundsOffset) { + SetBodyInnerHTML( + "<style>" + " body {" + " margin: 0px;" + " }" + " #scroller {" + " overflow-y: scroll;" + " width: 100px;" + " height: 100px;" + " margin-left: 7px;" + " margin-top: 11px;" + " }" + " .forceScroll {" + " height: 200px;" + " }" + "</style>" + "<div id='scroller'>" + " <div class='forceScroll'></div>" + "</div>"); + + Element* scroller = GetDocument().getElementById("scroller"); + scroller->setScrollTop(42); + + GetDocument().View()->UpdateAllLifecyclePhases(); + + const ObjectPaintProperties* scroll_properties = + scroller->GetLayoutObject()->FirstFragment()->PaintProperties(); + // Because the frameView is does not scroll, overflowHidden's scroll should be + // under the root. + auto* scroll_translation = scroll_properties->ScrollTranslation(); + auto* scroll_node = scroll_translation->ScrollNode(); + EXPECT_TRUE(scroll_node->Parent()->IsRoot()); + EXPECT_EQ(TransformationMatrix().Translate(0, -42), + scroll_translation->Matrix()); + // The scroll node should be offset by the margin. + EXPECT_EQ(IntPoint(7, 11), scroll_node->Offset()); + + scroller->setAttribute(HTMLNames::styleAttr, "border: 20px solid black;"); + GetDocument().View()->UpdateAllLifecyclePhases(); + // The scroll node should be offset by both the margin and border. + EXPECT_EQ(IntPoint(27, 31), scroll_node->Offset()); + + scroller->setAttribute(HTMLNames::styleAttr, + "border: 20px solid black;" + "transform: translate(20px, 30px);"); + GetDocument().View()->UpdateAllLifecyclePhases(); + // The scroll node's offset should not include margin if it has already been + // included in a paint offset node. + EXPECT_EQ(IntPoint(20, 20), scroll_node->Offset()); + EXPECT_EQ(TransformationMatrix().Translate(7, 11), + scroll_properties->PaintOffsetTranslation()->Matrix()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/resize_observer/ResizeObserverTest.cpp b/third_party/WebKit/Source/core/resize_observer/ResizeObserverTest.cpp index 6328e78..300c974 100644 --- a/third_party/WebKit/Source/core/resize_observer/ResizeObserverTest.cpp +++ b/third_party/WebKit/Source/core/resize_observer/ResizeObserverTest.cpp
@@ -7,7 +7,7 @@ #include "bindings/core/v8/ScriptController.h" #include "bindings/core/v8/ScriptSourceCode.h" #include "bindings/core/v8/V8GCController.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/resize_observer/ResizeObservation.h" #include "core/resize_observer/ResizeObserverController.h" #include "core/testing/sim/SimCompositor.h"
diff --git a/third_party/WebKit/Source/core/scheduler/ActiveConnectionThrottlingTest.cpp b/third_party/WebKit/Source/core/scheduler/ActiveConnectionThrottlingTest.cpp index 7d5a4a6..d1ccc35e 100644 --- a/third_party/WebKit/Source/core/scheduler/ActiveConnectionThrottlingTest.cpp +++ b/third_party/WebKit/Source/core/scheduler/ActiveConnectionThrottlingTest.cpp
@@ -2,7 +2,7 @@ // Use of this source code if governed by a BSD-style license that can be // found in LICENSE file. -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/WebLocalFrameImpl.h" #include "core/testing/sim/SimRequest.h" #include "core/testing/sim/SimTest.h"
diff --git a/third_party/WebKit/Source/core/testing/sim/SimCompositor.cpp b/third_party/WebKit/Source/core/testing/sim/SimCompositor.cpp index ed6fcae0..828399e 100644 --- a/third_party/WebKit/Source/core/testing/sim/SimCompositor.cpp +++ b/third_party/WebKit/Source/core/testing/sim/SimCompositor.cpp
@@ -4,7 +4,7 @@ #include "core/testing/sim/SimCompositor.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalFrame.h" #include "core/frame/LocalFrameView.h" #include "core/frame/WebLocalFrameImpl.h" @@ -57,7 +57,7 @@ LocalFrameView::SetInitialTracksPaintInvalidationsForTesting(false); } -void SimCompositor::SetWebView(WebViewBase& web_view) { +void SimCompositor::SetWebView(WebViewImpl& web_view) { web_view_ = &web_view; }
diff --git a/third_party/WebKit/Source/core/testing/sim/SimCompositor.h b/third_party/WebKit/Source/core/testing/sim/SimCompositor.h index 38d8a9f..cf3c3c0 100644 --- a/third_party/WebKit/Source/core/testing/sim/SimCompositor.h +++ b/third_party/WebKit/Source/core/testing/sim/SimCompositor.h
@@ -10,7 +10,7 @@ namespace blink { class SimDisplayItemList; -class WebViewBase; +class WebViewImpl; // Simulated very basic compositor that's capable of running the BeginMainFrame // processing steps on WebView: beginFrame, layout, paint. @@ -26,7 +26,7 @@ explicit SimCompositor(); ~SimCompositor(); - void SetWebView(WebViewBase&); + void SetWebView(WebViewImpl&); // Execute the BeginMainFrame processing steps, an approximation of what // cc::ThreadProxy::BeginMainFrame would do. @@ -53,7 +53,7 @@ bool needs_begin_frame_; bool defer_commits_; bool has_selection_; - WebViewBase* web_view_; + WebViewImpl* web_view_; double last_frame_time_monotonic_; WebColor background_color_; };
diff --git a/third_party/WebKit/Source/core/testing/sim/SimTest.cpp b/third_party/WebKit/Source/core/testing/sim/SimTest.cpp index 703e1a1..8c776ca 100644 --- a/third_party/WebKit/Source/core/testing/sim/SimTest.cpp +++ b/third_party/WebKit/Source/core/testing/sim/SimTest.cpp
@@ -5,7 +5,7 @@ #include "core/testing/sim/SimTest.h" #include "core/dom/Document.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "core/frame/LocalDOMWindow.h" #include "core/frame/WebLocalFrameImpl.h" #include "platform/LayoutTestSupport.h" @@ -62,7 +62,7 @@ return *WebView().MainFrameImpl()->GetFrame()->GetDocument(); } -WebViewBase& SimTest::WebView() { +WebViewImpl& SimTest::WebView() { return *web_view_helper_.WebView(); }
diff --git a/third_party/WebKit/Source/core/testing/sim/SimTest.h b/third_party/WebKit/Source/core/testing/sim/SimTest.h index 33d585e..ad5cc82 100644 --- a/third_party/WebKit/Source/core/testing/sim/SimTest.h +++ b/third_party/WebKit/Source/core/testing/sim/SimTest.h
@@ -15,7 +15,7 @@ namespace blink { -class WebViewBase; +class WebViewImpl; class WebLocalFrameImpl; class Document; class LocalDOMWindow; @@ -35,7 +35,7 @@ LocalDOMWindow& Window(); SimPage& Page(); Document& GetDocument(); - WebViewBase& WebView(); + WebViewImpl& WebView(); WebLocalFrameImpl& MainFrame(); const SimWebViewClient& WebViewClient() const; SimCompositor& Compositor();
diff --git a/third_party/WebKit/Source/core/workers/InstalledScriptsManager.h b/third_party/WebKit/Source/core/workers/InstalledScriptsManager.h index f0f85db..01fb3bd 100644 --- a/third_party/WebKit/Source/core/workers/InstalledScriptsManager.h +++ b/third_party/WebKit/Source/core/workers/InstalledScriptsManager.h
@@ -50,8 +50,8 @@ // Used on the worker thread. This is possible to return WTF::nullopt when the // script has already been served from this manager (i.e. the same script is - // read more than once). This can be blocked if the script is not streamed - // yet. + // read more than once) or when receiving the script from the browser has + // failed. This can be blocked if the script is not streamed yet. virtual Optional<ScriptData> GetScriptData(const KURL& script_url) = 0; };
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp index 8683fb7..02a4cebf 100644 --- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
@@ -411,29 +411,39 @@ String source_code; std::unique_ptr<Vector<char>> cached_meta_data; + bool should_terminate = false; if (RuntimeEnabledFeatures::ServiceWorkerScriptStreamingEnabled() && GetInstalledScriptsManager() && GetInstalledScriptsManager()->IsScriptInstalled(script_url)) { // GetScriptData blocks until the script is received from the browser. auto script_data = GetInstalledScriptsManager()->GetScriptData(script_url); - DCHECK(script_data); - DCHECK(source_code.IsEmpty()); - DCHECK(!cached_meta_data); - source_code = script_data->TakeSourceText(); - cached_meta_data = script_data->TakeMetaData(); - String referrer_policy = script_data->GetReferrerPolicy(); - ContentSecurityPolicyResponseHeaders - content_security_policy_response_headers = - script_data->GetContentSecurityPolicyResponseHeaders(); - worker_reporting_proxy_.DidLoadInstalledScript( - content_security_policy_response_headers, referrer_policy); + // |script_data| could be null if an error occurred in the browser process + // while trying to read the installed script. In that case, the worker + // thread will terminate after initialization of the global scope since + // PrepareForShutdownOnWorkerThread() assumes the global scope has already + // been initialized. + if (!script_data) { + should_terminate = true; + } else { + DCHECK(source_code.IsEmpty()); + DCHECK(!cached_meta_data); + source_code = script_data->TakeSourceText(); + cached_meta_data = script_data->TakeMetaData(); - global_scope_creation_params->content_security_policy_raw_headers = - std::move(content_security_policy_response_headers); - global_scope_creation_params->referrer_policy = referrer_policy; - global_scope_creation_params->origin_trial_tokens = - script_data->CreateOriginTrialTokens(); + global_scope_creation_params->content_security_policy_raw_headers = + script_data->GetContentSecurityPolicyResponseHeaders(); + global_scope_creation_params->referrer_policy = + script_data->GetReferrerPolicy(); + global_scope_creation_params->origin_trial_tokens = + script_data->CreateOriginTrialTokens(); + // This may block until CSP and referrer policy are set on the main + // thread. + worker_reporting_proxy_.DidLoadInstalledScript( + global_scope_creation_params->content_security_policy_raw_headers + .value(), + global_scope_creation_params->referrer_policy); + } } else { source_code = std::move(global_scope_creation_params->source_code); cached_meta_data = @@ -473,10 +483,11 @@ if (start_mode == kPauseWorkerGlobalScopeOnStart) StartRunningDebuggerTasksOnPauseOnWorkerThread(); - if (CheckRequestedToTerminateOnWorkerThread()) { + if (CheckRequestedToTerminateOnWorkerThread() || should_terminate) { // Stop further worker tasks from running after this point. WorkerThread // was requested to terminate before initialization or during running - // debugger tasks. performShutdownOnWorkerThread() will be called soon. + // debugger tasks, or loading the installed main script + // failed. PerformShutdownOnWorkerThread() will be called soon. PrepareForShutdownOnWorkerThread(); return; }
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn index 8a953f55..67f6f69 100644 --- a/third_party/WebKit/Source/devtools/BUILD.gn +++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -136,10 +136,12 @@ "front_end/components/module.json", "front_end/components/Reload.js", "front_end/console/ConsoleContextSelector.js", + "front_end/console/ConsoleSidebar.js", "front_end/console/ConsolePanel.js", "front_end/console/ConsolePrompt.js", "front_end/console/consoleView.css", "front_end/console/consoleContextSelector.css", + "front_end/console/consoleSidebar.css", "front_end/console/ConsoleView.js", "front_end/console/ConsoleViewMessage.js", "front_end/console/ConsoleViewport.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/Tests.js b/third_party/WebKit/Source/devtools/front_end/Tests.js index 34b4a06..7d2ee70f 100644 --- a/third_party/WebKit/Source/devtools/front_end/Tests.js +++ b/third_party/WebKit/Source/devtools/front_end/Tests.js
@@ -724,6 +724,24 @@ {type: 'keyUp', windowsVirtualKeyCode: 0x23, key: 'End'}); }; + // Simple sanity check to make sure network throttling is wired up + // See crbug.com/747724 + TestSuite.prototype.testOfflineNetworkConditions = async function() { + var test = this; + SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.OfflineConditions); + + function finishRequest(request) { + test.assertEquals( + 'net::ERR_INTERNET_DISCONNECTED', request.localizedFailDescription, 'Request should have failed'); + test.releaseControl(); + } + + this.addSniffer(SDK.NetworkDispatcher.prototype, '_finishNetworkRequest', finishRequest); + + test.takeControl(); + test.evaluateInConsole_('window.location.reload(true);', function(resultText) {}); + }; + TestSuite.prototype.testEmulateNetworkConditions = function() { var test = this;
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleSidebar.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleSidebar.js new file mode 100644 index 0000000..7340e5c --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleSidebar.js
@@ -0,0 +1,143 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @implements {UI.ListDelegate<!Console.ConsoleSidebar.GroupItem>} + */ +Console.ConsoleSidebar = class extends UI.VBox { + constructor() { + super(true); + this.registerRequiredCSS('console/consoleSidebar.css'); + this.setMinimumSize(50, 0); + + /** @type {!UI.ListModel<!Console.ConsoleSidebar.GroupItem>} */ + this._items = new UI.ListModel(); + /** @type {!UI.ListControl<!Console.ConsoleSidebar.GroupItem>} */ + this._list = new UI.ListControl(this._items, this, UI.ListMode.EqualHeightItems); + this._list.element.classList.add('list'); + this.contentElement.appendChild(this._list.element); + + this._items.replaceAll([Console.ConsoleSidebar._createAllGroup()]); + this._list.selectItem(this._items.at(0)); + + /** @type {!Set<string>} */ + this._contexts = new Set(); + /** @type {!Set<!Console.ConsoleSidebar.GroupItem>} */ + this._pendingItemsToAdd = new Set(); + this._pendingClear = false; + } + + /** + * @return {!Console.ConsoleSidebar.GroupItem} + */ + static _createAllGroup() { + return {context: Console.ConsoleSidebar.AllContextsFilter, name: 'All'}; + } + + /** + * @override + */ + wasShown() { + // ListControl's viewport does not update when hidden. + this._list.viewportResized(); + } + + /** + * @override + */ + onResize() { + this._list.viewportResized(); + } + + /** + * @param {!Console.ConsoleSidebar.GroupItem} item + */ + addGroup(item) { + if (!Runtime.experiments.isEnabled('logManagement')) + return; + if (this._contexts.has(item.context)) + return; + this._contexts.add(item.context); + this._pendingItemsToAdd.add(item); + } + + clear() { + if (!Runtime.experiments.isEnabled('logManagement')) + return; + this._contexts.clear(); + this._pendingItemsToAdd.clear(); + this._pendingClear = true; + } + + refresh() { + if (!Runtime.experiments.isEnabled('logManagement')) + return; + if (this._pendingClear) { + this._items.replaceAll([Console.ConsoleSidebar._createAllGroup()]); + this._list.selectItem(this._items.at(0)); + this._pendingClear = false; + } + if (this._pendingItemsToAdd.size > 0) { + this._items.replaceRange(this._items.length, this._items.length, Array.from(this._pendingItemsToAdd)); + this._pendingItemsToAdd.clear(); + } + } + + /** + * @override + * @param {!Console.ConsoleSidebar.GroupItem} item + * @return {!Element} + */ + createElementForItem(item) { + var element = createElementWithClass('div', 'context-item'); + element.createChild('div', 'name').textContent = item.name; + element.title = item.name; + return element; + } + + /** + * @override + * @param {!Console.ConsoleSidebar.GroupItem} item + * @return {number} + */ + heightForItem(item) { + return 28; + } + + /** + * @override + * @param {!Console.ConsoleSidebar.GroupItem} item + * @return {boolean} + */ + isItemSelectable(item) { + return true; + } + + /** + * @override + * @param {?Console.ConsoleSidebar.GroupItem} from + * @param {?Console.ConsoleSidebar.GroupItem} to + * @param {?Element} fromElement + * @param {?Element} toElement + */ + selectedItemChanged(from, to, fromElement, toElement) { + if (fromElement) + fromElement.classList.remove('selected'); + if (!to || !toElement) + return; + + toElement.classList.add('selected'); + this.dispatchEventToListeners(Console.ConsoleSidebar.Events.ContextSelected, to.context); + } +}; + +Console.ConsoleSidebar.AllContextsFilter = Symbol('All'); + +/** @enum {symbol} */ +Console.ConsoleSidebar.Events = { + ContextSelected: Symbol('ContextSelected') +}; + +/** @typedef {{context: (string|symbol), name: string}} */ +Console.ConsoleSidebar.GroupItem;
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js index 30ccfb9..09963dae 100644 --- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js +++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
@@ -40,10 +40,23 @@ this._searchableView = new UI.SearchableView(this); this._searchableView.setPlaceholder(Common.UIString('Find string in logs')); this._searchableView.setMinimalSearchQuerySize(0); - this._searchableView.show(this.element); + this._sidebar = new Console.ConsoleSidebar(); + var toolbar = new UI.Toolbar('', this.element); + if (Runtime.experiments.isEnabled('logManagement')) { + this._splitWidget = + new UI.SplitWidget(true /* isVertical */, false /* secondIsSidebar */, 'console.sidebar.width', 100); + this._splitWidget.setMainWidget(this._searchableView); + this._splitWidget.setSidebarWidget(this._sidebar); + this._splitWidget.hideSidebar(); + this._splitWidget.show(this.element); + toolbar.appendToolbarItem(this._splitWidget.createShowHideSidebarButton('console sidebar')); + } else { + this._searchableView.show(this.element); + } this._contentsElement = this._searchableView.element; - this._contentsElement.classList.add('console-view'); + this.element.classList.add('console-view'); + /** @type {!Array.<!Console.ConsoleViewMessage>} */ this._visibleViewMessages = []; this._urlToMessageCount = {}; @@ -64,7 +77,6 @@ this._showSettingsPaneSetting, 'largeicon-settings-gear', Common.UIString('Console settings')); this._progressToolbarItem = new UI.ToolbarItem(createElement('div')); - var toolbar = new UI.Toolbar('', this._contentsElement); toolbar.appendToolbarItem(UI.Toolbar.createActionButton( /** @type {!UI.Action }*/ (UI.actionRegistry.action('console.clear')))); toolbar.appendSeparator(); @@ -176,6 +188,10 @@ this._messagesElement.addEventListener('mouseleave', this._updateStickToBottomOnMouseUp.bind(this), false); this._messagesElement.addEventListener('wheel', this._updateStickToBottomOnWheel.bind(this), false); + this._sidebar.addEventListener(Console.ConsoleSidebar.Events.ContextSelected, event => { + this._filter.setContext(/** @type {string|symbol} */ (event.data)); + }); + ConsoleModel.consoleModel.addEventListener( ConsoleModel.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this); ConsoleModel.consoleModel.addEventListener( @@ -357,6 +373,7 @@ this._updateMessageList(); delete this._needsFullUpdate; } else { + this._sidebar.refresh(); this._viewport.invalidate(); } return Promise.resolve(); @@ -464,6 +481,10 @@ * @param {!Console.ConsoleViewMessage} viewMessage */ _appendMessageToEnd(viewMessage) { + var context = viewMessage.consoleMessage().context; + if (context) + this._sidebar.addGroup({name: context, context: context}); + if (!this._filter.shouldBeVisible(viewMessage)) { this._hiddenByFilterCount++; return; @@ -520,6 +541,7 @@ _consoleCleared() { this._currentMatchRangeIndex = -1; this._consoleMessages = []; + this._sidebar.clear(); this._updateMessageList(); this._hidePromptSuggestBox(); this._viewport.setStickToBottom(true); @@ -645,6 +667,7 @@ this._appendMessageToEnd(this._consoleMessages[i]); this._updateFilterStatus(); this._searchableView.updateSearchMatchesCount(this._regexMatchRanges.length); + this._sidebar.refresh(); this._viewport.invalidate(); } @@ -983,6 +1006,7 @@ */ constructor(filterChangedCallback) { this._filterChanged = filterChangedCallback; + this._context = Console.ConsoleSidebar.AllContextsFilter; this._messageURLFiltersSetting = Common.settings.createSetting('messageURLFilters', {}); this._messageLevelFiltersSetting = Console.ConsoleViewFilter.levelFilterSetting(); @@ -1044,6 +1068,16 @@ return result; } + /** + * @param {string|symbol} context + */ + setContext(context) { + if (this._context !== context) { + this._context = context; + this._filterChanged(); + } + } + _updateLevelMenuButtonText() { var isAll = true; var isDefault = true; @@ -1178,10 +1212,14 @@ message.source !== ConsoleModel.ConsoleMessage.MessageSource.ConsoleAPI) return false; + if (this._context !== Console.ConsoleSidebar.AllContextsFilter && message.context !== this._context) + return false; + return true; } reset() { + this._context = Console.ConsoleSidebar.AllContextsFilter; this._messageURLFiltersSetting.set({}); this._messageLevelFiltersSetting.set(Console.ConsoleViewFilter.defaultLevelsFilterValue()); this._filterByExecutionContextSetting.set(false);
diff --git a/third_party/WebKit/Source/devtools/front_end/console/consoleSidebar.css b/third_party/WebKit/Source/devtools/front_end/console/consoleSidebar.css new file mode 100644 index 0000000..6dfb178f --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/console/consoleSidebar.css
@@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +:host { + background-color: #eee; + overflow: hidden; +} + +.list { + flex: 1; +} + +.context-item { + cursor: pointer; + overflow: hidden; + text-overflow: ellipsis; + padding: 6px 6px 6px 16px; + height: 28px; +} + +.context-item.selected { + background-color: #3c7bd6; +} + +.name { + display: inline-block; + white-space: nowrap; + margin-bottom: 10px; +} + +.context-item.selected .name { + color: white; +}
diff --git a/third_party/WebKit/Source/devtools/front_end/console/module.json b/third_party/WebKit/Source/devtools/front_end/console/module.json index f9ff126..ed35c62 100644 --- a/third_party/WebKit/Source/devtools/front_end/console/module.json +++ b/third_party/WebKit/Source/devtools/front_end/console/module.json
@@ -169,6 +169,7 @@ ], "scripts": [ "ConsoleContextSelector.js", + "ConsoleSidebar.js", "ConsoleViewport.js", "ConsoleViewMessage.js", "ConsolePrompt.js", @@ -177,6 +178,7 @@ ], "resources": [ "consoleContextSelector.css", + "consoleSidebar.css", "consoleView.css" ] }
diff --git a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js index 87348c9..369f4ff 100644 --- a/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js +++ b/third_party/WebKit/Source/devtools/front_end/console_model/ConsoleModel.js
@@ -246,7 +246,7 @@ runtimeModel, ConsoleModel.ConsoleMessage.MessageSource.ConsoleAPI, level, /** @type {string} */ (message), call.type, callFrame ? callFrame.url : undefined, callFrame ? callFrame.lineNumber : undefined, callFrame ? callFrame.columnNumber : undefined, undefined, - call.args, call.stackTrace, call.timestamp, call.executionContextId, undefined); + call.args, call.stackTrace, call.timestamp, call.executionContextId, undefined, undefined, call.context); this.addMessage(consoleMessage); } @@ -401,10 +401,11 @@ * @param {!Protocol.Runtime.ExecutionContextId=} executionContextId * @param {?string=} scriptId * @param {?string=} workerId + * @param {string=} context */ constructor( runtimeModel, source, level, messageText, type, url, line, column, requestId, parameters, stackTrace, timestamp, - executionContextId, scriptId, workerId) { + executionContextId, scriptId, workerId, context) { this._runtimeModel = runtimeModel; this.source = source; this.level = /** @type {?ConsoleModel.ConsoleMessage.MessageLevel} */ (level); @@ -443,6 +444,9 @@ else if (this.stackTrace) this.executionContextId = this._runtimeModel.executionContextForStackTrace(this.stackTrace); } + + if (context) + this.context = context.match(/[^#]*/)[0]; } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js index 4bed8ac..c8072e4 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -741,7 +741,9 @@ this._splitMode = splitMode; var extensionSidebarPanes = Extensions.extensionServer.sidebarPanes(); + var lastSelectedTabId = null; if (this.sidebarPaneView) { + lastSelectedTabId = this.sidebarPaneView.tabbedPane().selectedTabId; this.sidebarPaneView.tabbedPane().detach(); this._splitWidget.uninstallResizer(this.sidebarPaneView.tabbedPane().headerElement()); } @@ -821,6 +823,9 @@ for (var i = 0; i < extensionSidebarPanes.length; ++i) this._addExtensionSidebarPane(extensionSidebarPanes[i]); + if (lastSelectedTabId) + this.sidebarPaneView.tabbedPane().selectTab(lastSelectedTabId); + this._splitWidget.setSidebarWidget(this.sidebarPaneView.tabbedPane()); }
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/SensorsView.js b/third_party/WebKit/Source/devtools/front_end/emulation/SensorsView.js index bbe082ee..6d1bf14 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/SensorsView.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/SensorsView.js
@@ -431,9 +431,18 @@ select.appendChild(new Option(Common.UIString('Force enabled'), 'enabled')); select.addEventListener('change', applyTouch, false); + var reloadWarning = groupElement.createChild('div', 'reload-warning hidden'); + reloadWarning.textContent = Common.UIString('*Requires reload'); + function applyTouch() { for (var emulationModel of SDK.targetManager.models(SDK.EmulationModel)) emulationModel.overrideEmulateTouch(select.value === 'enabled'); + reloadWarning.classList.remove('hidden'); + var resourceTreeModel = SDK.targetManager.models(SDK.ResourceTreeModel)[0]; + if (resourceTreeModel) { + resourceTreeModel.once(SDK.ResourceTreeModel.Events.MainFrameNavigated) + .then(() => reloadWarning.classList.add('hidden')); + } } } };
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/sensors.css b/third_party/WebKit/Source/devtools/front_end/emulation/sensors.css index 16c02e9..03c1311 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/sensors.css +++ b/third_party/WebKit/Source/devtools/front_end/emulation/sensors.css
@@ -304,3 +304,8 @@ margin-bottom: 12px; background: #f1f1f1; } + +.reload-warning { + align-self: center; + margin-left: 10px; +}
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js index 8d483093..55bf506 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/Main.js +++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -119,6 +119,7 @@ Runtime.experiments.register('continueToLocationMarkers', 'Continue to location markers', true); Runtime.experiments.register('emptySourceMapAutoStepping', 'Empty sourcemap auto-stepping'); Runtime.experiments.register('inputEventsOnTimelineOverview', 'Input events on Timeline overview', true); + Runtime.experiments.register('logManagement', 'Log management', true); Runtime.experiments.register('liveSASS', 'Live SASS'); Runtime.experiments.register('networkGroupingRequests', 'Network request groups support', true); Runtime.experiments.register('objectPreviews', 'Object previews', true);
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js index ca8ee94..659b212 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
@@ -804,10 +804,12 @@ } /** - * @param {!RegExp=} regexp + * @param {?RegExp} regexp * @return {!Array.<!Object>} */ highlightMatchedSubstring(regexp) { + if (!regexp) + return []; // Ensure element is created. this.element(); var domChanges = [];
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js index 7a281d3..a8821f3 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
@@ -27,10 +27,10 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + /** * @implements {UI.Searchable} * @implements {SDK.SDKModelObserver<!SDK.NetworkManager>} - * @unrestricted */ Network.NetworkLogView = class extends UI.VBox { /** @@ -43,33 +43,36 @@ this.setMinimumSize(50, 64); this.registerRequiredCSS('network/networkLogView.css'); + this.element.id = 'network-container'; + this._networkHideDataURLSetting = Common.settings.createSetting('networkHideDataURL', false); this._networkResourceTypeFiltersSetting = Common.settings.createSetting('networkResourceTypeFilters', {}); - this._filterBar = filterBar; this._rawRowHeight = 0; this._progressBarContainer = progressBarContainer; this._networkLogLargeRowsSetting = networkLogLargeRowsSetting; this._networkLogLargeRowsSetting.addChangeListener(updateRowHeight.bind(this), this); + /** + * @this {Network.NetworkLogView} + */ + function updateRowHeight() { + this._rawRowHeight = !!this._networkLogLargeRowsSetting.get() ? 41 : 21; + this._rowHeight = this._computeRowHeight(); + } + this._rawRowHeight = 0; + this._rowHeight = 0; + updateRowHeight.call(this); + /** @type {!Network.NetworkTransferTimeCalculator} */ this._timeCalculator = new Network.NetworkTransferTimeCalculator(); /** @type {!Network.NetworkTransferDurationCalculator} */ this._durationCalculator = new Network.NetworkTransferDurationCalculator(); this._calculator = this._timeCalculator; - /** - * @this {Network.NetworkLogView} - */ - function updateRowHeight() { - /** @type {number} */ - this._rawRowHeight = !!this._networkLogLargeRowsSetting.get() ? 41 : 21; - this._updateRowHeight(); - } - updateRowHeight.call(this); - this._columns = new Network.NetworkLogViewColumns( this, this._timeCalculator, this._durationCalculator, networkLogLargeRowsSetting); + this._columns.show(this.element); /** @type {!Set<!SDK.NetworkRequest>} */ this._staleRequests = new Set(); @@ -86,6 +89,14 @@ this._timeFilter = null; /** @type {?Network.NetworkNode} */ this._hoveredNode = null; + /** @type {?Element} */ + this._recordingHint = null; + /** @type {?number} */ + this._refreshRequestId = null; + /** @type {?RegExp} */ + this._searchRegex = null; + /** @type {?Network.NetworkRequestNode} */ + this._highlightedNode = null; this._currentMatchedRequestNode = null; this._currentMatchedRequestIndex = -1; @@ -94,6 +105,7 @@ this.badgePool = new ProductRegistry.BadgePool(); this._recording = false; + this._needsRefresh = false; this._headerHeight = 0; @@ -104,9 +116,30 @@ /** @type {?Network.GroupLookupInterface} */ this._activeGroupLookup = null; - this._addFilters(); + this._textFilterUI = new UI.TextFilterUI(true); + this._textFilterUI.addEventListener(UI.FilterUI.Events.FilterChanged, this._filterChanged, this); + filterBar.addFilter(this._textFilterUI); + + this._dataURLFilterUI = new UI.CheckboxFilterUI( + 'hide-data-url', Common.UIString('Hide data URLs'), true, this._networkHideDataURLSetting); + this._dataURLFilterUI.addEventListener(UI.FilterUI.Events.FilterChanged, this._filterChanged.bind(this), this); + filterBar.addFilter(this._dataURLFilterUI); + + var filterItems = Object.values(Common.resourceCategories) + .map(category => ({name: category.title, label: category.shortTitle, title: category.title})); + this._resourceCategoryFilterUI = new UI.NamedBitSetFilterUI(filterItems, this._networkResourceTypeFiltersSetting); + this._resourceCategoryFilterUI.addEventListener( + UI.FilterUI.Events.FilterChanged, this._filterChanged.bind(this), this); + filterBar.addFilter(this._resourceCategoryFilterUI); + + this._suggestionBuilder = new Network.FilterSuggestionBuilder(Network.NetworkLogView._searchKeys); this._resetSuggestionBuilder(); - this._initializeView(); + + this._dataGrid = this._columns.dataGrid(); + this._setupDataGrid(); + this._columns.sortByCurrentColumn(); + + this._summaryBarElement = this.element.createChild('div', 'network-summary-bar'); new UI.DropTarget( this.element, [UI.DropTarget.Types.Files], Common.UIString('Drop HAR files here'), this._handleDrop.bind(this)); @@ -437,8 +470,11 @@ this._invalidateAllItems(); } - _updateRowHeight() { - this._rowHeight = Math.floor(this._rawRowHeight * window.devicePixelRatio) / window.devicePixelRatio; + /** + * @return {number} + */ + _computeRowHeight() { + return Math.floor(this._rawRowHeight * window.devicePixelRatio) / window.devicePixelRatio; } /** @@ -515,30 +551,7 @@ this._dataGrid.selectedNode.deselect(); } - _addFilters() { - this._textFilterUI = new UI.TextFilterUI(true); - this._textFilterUI.addEventListener(UI.FilterUI.Events.FilterChanged, this._filterChanged, this); - this._filterBar.addFilter(this._textFilterUI); - - var dataURLSetting = this._networkHideDataURLSetting; - this._dataURLFilterUI = - new UI.CheckboxFilterUI('hide-data-url', Common.UIString('Hide data URLs'), true, dataURLSetting); - this._dataURLFilterUI.addEventListener(UI.FilterUI.Events.FilterChanged, this._filterChanged.bind(this), this); - this._filterBar.addFilter(this._dataURLFilterUI); - - var filterItems = []; - for (var categoryId in Common.resourceCategories) { - var category = Common.resourceCategories[categoryId]; - filterItems.push({name: category.title, label: category.shortTitle, title: category.title}); - } - this._resourceCategoryFilterUI = new UI.NamedBitSetFilterUI(filterItems, this._networkResourceTypeFiltersSetting); - this._resourceCategoryFilterUI.addEventListener( - UI.FilterUI.Events.FilterChanged, this._filterChanged.bind(this), this); - this._filterBar.addFilter(this._resourceCategoryFilterUI); - } - _resetSuggestionBuilder() { - this._suggestionBuilder = new Network.FilterSuggestionBuilder(Network.NetworkLogView._searchKeys); this._suggestionBuilder.addItem(Network.NetworkLogView.FilterType.Is, Network.NetworkLogView.IsFilterType.Running); this._suggestionBuilder.addItem( Network.NetworkLogView.FilterType.Is, Network.NetworkLogView.IsFilterType.FromCache); @@ -557,17 +570,6 @@ this._filterRequests(); } - _initializeView() { - this.element.id = 'network-container'; - this._setupDataGrid(); - - this._columns.show(this.element); - - this._summaryBarElement = this.element.createChild('div', 'network-summary-bar'); - - this._columns.sortByCurrentColumn(); - } - _showRecordingHint() { this._hideRecordingHint(); this._recordingHint = this.element.createChild('div', 'network-status-pane fill'); @@ -592,7 +594,7 @@ _hideRecordingHint() { if (this._recordingHint) this._recordingHint.remove(); - delete this._recordingHint; + this._recordingHint = null; } /** @@ -610,8 +612,6 @@ } _setupDataGrid() { - /** @type {!DataGrid.SortableDataGrid<!Network.NetworkNode>} */ - this._dataGrid = this._columns.dataGrid(); this._dataGrid.setRowContextMenuCallback((contextMenu, node) => { var request = node.request(); if (request) @@ -624,6 +624,7 @@ this._dataGrid.element.addEventListener('mousedown', this._dataGridMouseDown.bind(this), true); this._dataGrid.element.addEventListener('mousemove', this._dataGridMouseMove.bind(this), true); this._dataGrid.element.addEventListener('mouseleave', () => this._setHoveredNode(null), true); + return this._dataGrid; } /** @@ -866,7 +867,7 @@ * @override */ onResize() { - this._updateRowHeight(); + this._rowHeight = this._computeRowHeight(); } /** @@ -885,7 +886,7 @@ if (this._refreshRequestId) { this.element.window().cancelAnimationFrame(this._refreshRequestId); - delete this._refreshRequestId; + this._refreshRequestId = null; } this.removeAllNodeHighlights(); @@ -990,7 +991,6 @@ } _reset() { - this._requestWithHighlightedInitiators = null; this.dispatchEventToListeners(Network.NetworkLogView.Events.RequestSelected, null); this._clearSearchMatchedList(); @@ -1585,7 +1585,7 @@ * @override */ searchCanceled() { - delete this._searchRegex; + this._searchRegex = null; this._clearSearchMatchedList(); this.dispatchEventToListeners(Network.NetworkLogView.Events.SearchCountUpdated, 0); } @@ -1597,7 +1597,7 @@ this.removeAllNodeHighlights(); var node = request[Network.NetworkLogView._networkNodeSymbol]; - if (node && this.attached) { + if (node && node.attached()) { node.reveal(); this._highlightNode(node); } @@ -1606,7 +1606,7 @@ removeAllNodeHighlights() { if (this._highlightedNode) { this._highlightedNode.element().classList.remove('highlighted-row'); - delete this._highlightedNode; + this._highlightedNode = null; } }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/EmulationModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/EmulationModel.js index 825541d..df0e5bc 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/EmulationModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/EmulationModel.js
@@ -132,29 +132,12 @@ var configuration = { enabled: this._touchEnabled, configuration: this._touchMobile ? 'mobile' : 'desktop', - scriptId: '' }; if (this._customTouchEnabled) - configuration = {enabled: true, configuration: 'mobile', scriptId: ''}; + configuration = {enabled: true, configuration: 'mobile'}; if (this._overlayModel && this._overlayModel.inspectModeEnabled()) - configuration = {enabled: false, configuration: 'mobile', scriptId: ''}; - - /** - * @suppressGlobalPropertiesCheck - */ - const injectedFunction = function() { - const touchEvents = ['ontouchstart', 'ontouchend', 'ontouchmove', 'ontouchcancel']; - var recepients = [window.__proto__, document.__proto__]; - for (var i = 0; i < touchEvents.length; ++i) { - for (var j = 0; j < recepients.length; ++j) { - if (!(touchEvents[i] in recepients[j])) { - Object.defineProperty( - recepients[j], touchEvents[i], {value: null, writable: true, configurable: true, enumerable: true}); - } - } - } - }; + configuration = {enabled: false, configuration: 'mobile'}; if (!this._touchConfiguration.enabled && !configuration.enabled) return; @@ -162,15 +145,7 @@ this._touchConfiguration.configuration === configuration.configuration) return; - if (this._touchConfiguration.scriptId) - this._pageAgent.removeScriptToEvaluateOnLoad(this._touchConfiguration.scriptId); this._touchConfiguration = configuration; - if (configuration.enabled) { - this._pageAgent.addScriptToEvaluateOnLoad('(' + injectedFunction.toString() + ')()').then(scriptId => { - this._touchConfiguration.scriptId = scriptId || ''; - }); - } - this._emulationAgent.setTouchEmulationEnabled(configuration.enabled, configuration.configuration); } };
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js index 9081df8..7f762984 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js
@@ -396,10 +396,17 @@ * @param {number} executionContextId * @param {number} timestamp * @param {!Protocol.Runtime.StackTrace=} stackTrace + * @param {string=} context */ - _consoleAPICalled(type, args, executionContextId, timestamp, stackTrace) { - var consoleAPICall = - {type: type, args: args, executionContextId: executionContextId, timestamp: timestamp, stackTrace: stackTrace}; + _consoleAPICalled(type, args, executionContextId, timestamp, stackTrace, context) { + var consoleAPICall = { + type: type, + args: args, + executionContextId: executionContextId, + timestamp: timestamp, + stackTrace: stackTrace, + context: context + }; this.dispatchEventToListeners(SDK.RuntimeModel.Events.ConsoleAPICalled, consoleAPICall); } @@ -512,9 +519,10 @@ * @param {number} executionContextId * @param {number} timestamp * @param {!Protocol.Runtime.StackTrace=} stackTrace + * @param {string=} context */ - consoleAPICalled(type, args, executionContextId, timestamp, stackTrace) { - this._runtimeModel._consoleAPICalled(type, args, executionContextId, timestamp, stackTrace); + consoleAPICalled(type, args, executionContextId, timestamp, stackTrace, context) { + this._runtimeModel._consoleAPICalled(type, args, executionContextId, timestamp, stackTrace, context); } /**
diff --git a/third_party/WebKit/Source/modules/exported/WebStorageEventDispatcherImpl.cpp b/third_party/WebKit/Source/modules/exported/WebStorageEventDispatcherImpl.cpp index 1b4b0e3..a7ed35f1 100644 --- a/third_party/WebKit/Source/modules/exported/WebStorageEventDispatcherImpl.cpp +++ b/third_party/WebKit/Source/modules/exported/WebStorageEventDispatcherImpl.cpp
@@ -30,7 +30,7 @@ #include "public/web/WebStorageEventDispatcher.h" -#include "core/exported/WebViewBase.h" +#include "core/exported/WebViewImpl.h" #include "modules/storage/StorageArea.h" #include "platform/weborigin/KURL.h" #include "platform/weborigin/SecurityOrigin.h"
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp index d1a1b99..26731351 100644 --- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp +++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
@@ -148,6 +148,17 @@ if (!frame_data) return false; + if (!in_animation_frame_) { + Document* doc = navigator_vr_->GetDocument(); + if (doc) { + doc->AddConsoleMessage( + ConsoleMessage::Create(kRenderingMessageSource, kWarningMessageLevel, + "getFrameData must be called within a " + "VRDisplay.requestAnimationFrame callback.")); + } + return false; + } + if (depth_near_ == depth_far_) return false;
diff --git a/third_party/WebKit/Source/platform/InstanceCounters.cpp b/third_party/WebKit/Source/platform/InstanceCounters.cpp index f4802ae..a6413f75 100644 --- a/third_party/WebKit/Source/platform/InstanceCounters.cpp +++ b/third_party/WebKit/Source/platform/InstanceCounters.cpp
@@ -34,15 +34,7 @@ int InstanceCounters::counters_[kCounterTypeLength]; -// Counts only nodes for a performance reason. Many node are created and atomic -// barriers or locks should be avoided (crbug/641019). -int InstanceCounters::node_counter_; - int InstanceCounters::CounterValue(CounterType type) { - if (type == kNodeCounter) { - DCHECK(IsMainThread()); - return node_counter_; - } return AcquireLoad(&counters_[type]); }
diff --git a/third_party/WebKit/Source/platform/InstanceCounters.h b/third_party/WebKit/Source/platform/InstanceCounters.h index aebca57..da26b48 100644 --- a/third_party/WebKit/Source/platform/InstanceCounters.h +++ b/third_party/WebKit/Source/platform/InstanceCounters.h
@@ -37,54 +37,56 @@ namespace blink { +#define INSTANCE_COUNTERS_LIST(V) \ + V(AudioHandler) \ + V(Document) \ + V(Frame) \ + V(JSEventListener) \ + V(LayoutObject) \ + V(MediaKeySession) \ + V(MediaKeys) \ + V(Node) \ + V(Resource) \ + V(ScriptPromise) \ + V(SuspendableObject) \ + V(V8PerContextData) \ + V(WorkerGlobalScope) + class InstanceCounters { STATIC_ONLY(InstanceCounters); public: enum CounterType { - kAudioHandlerCounter, - kDocumentCounter, - kFrameCounter, - kJSEventListenerCounter, - kLayoutObjectCounter, - kMediaKeySessionCounter, - kMediaKeysCounter, - kNodeCounter, - kResourceCounter, - kScriptPromiseCounter, - kSuspendableObjectCounter, - kV8PerContextDataCounter, - kWorkerGlobalScopeCounter, - - // This value must be the last. - kCounterTypeLength, +#define DECLARE_INSTANCE_COUNTER(name) k##name##Counter, + INSTANCE_COUNTERS_LIST(DECLARE_INSTANCE_COUNTER) +#undef DECLARE_INSTANCE_COUNTER + kCounterTypeLength }; static inline void IncrementCounter(CounterType type) { - DCHECK_NE(type, kNodeCounter); - AtomicIncrement(&counters_[type]); + // There are lots of nodes created. Atomic barriers or locks + // should be avoided for the sake of performance. See crbug.com/641019 + if (type == kNodeCounter) { + DCHECK(IsMainThread()); + ++counters_[kNodeCounter]; + } else { + AtomicIncrement(&counters_[type]); + } } static inline void DecrementCounter(CounterType type) { - DCHECK_NE(type, kNodeCounter); - AtomicDecrement(&counters_[type]); - } - - static inline void IncrementNodeCounter() { - DCHECK(IsMainThread()); - node_counter_++; - } - - static inline void DecrementNodeCounter() { - DCHECK(IsMainThread()); - node_counter_--; + if (type == kNodeCounter) { + DCHECK(IsMainThread()); + --counters_[kNodeCounter]; + } else { + AtomicDecrement(&counters_[type]); + } } PLATFORM_EXPORT static int CounterValue(CounterType); private: - PLATFORM_EXPORT static int counters_[kCounterTypeLength]; - PLATFORM_EXPORT static int node_counter_; + PLATFORM_EXPORT static int counters_[]; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/InstanceCountersMemoryDumpProvider.cc b/third_party/WebKit/Source/platform/InstanceCountersMemoryDumpProvider.cc index 6b2f9c5..bf3678e 100644 --- a/third_party/WebKit/Source/platform/InstanceCountersMemoryDumpProvider.cc +++ b/third_party/WebKit/Source/platform/InstanceCountersMemoryDumpProvider.cc
@@ -20,51 +20,12 @@ const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* memory_dump) { using base::trace_event::MemoryAllocatorDump; -#define DUMP_COUNTER(CounterType) \ - { \ - MemoryAllocatorDump* counter_dump = \ - memory_dump->CreateAllocatorDump("counter/" #CounterType); \ - counter_dump->AddScalar("object_count", \ - MemoryAllocatorDump::kUnitsObjects, \ - InstanceCounters::CounterValue( \ - InstanceCounters::k##CounterType##Counter)); \ - break; \ - } - - for (int i = 0; i < InstanceCounters::kCounterTypeLength; ++i) { - InstanceCounters::CounterType type = - static_cast<InstanceCounters::CounterType>(i); - switch (type) { - case InstanceCounters::kAudioHandlerCounter: - DUMP_COUNTER(AudioHandler) - case InstanceCounters::kDocumentCounter: - DUMP_COUNTER(Document) - case InstanceCounters::kFrameCounter: - DUMP_COUNTER(Frame) - case InstanceCounters::kJSEventListenerCounter: - DUMP_COUNTER(JSEventListener) - case InstanceCounters::kLayoutObjectCounter: - DUMP_COUNTER(LayoutObject) - case InstanceCounters::kMediaKeySessionCounter: - DUMP_COUNTER(MediaKeySession) - case InstanceCounters::kMediaKeysCounter: - DUMP_COUNTER(MediaKeys) - case InstanceCounters::kNodeCounter: - DUMP_COUNTER(Node) - case InstanceCounters::kResourceCounter: - DUMP_COUNTER(Resource) - case InstanceCounters::kScriptPromiseCounter: - DUMP_COUNTER(ScriptPromise) - case InstanceCounters::kSuspendableObjectCounter: - DUMP_COUNTER(SuspendableObject) - case InstanceCounters::kV8PerContextDataCounter: - DUMP_COUNTER(V8PerContextData) - case InstanceCounters::kWorkerGlobalScopeCounter: - DUMP_COUNTER(WorkerGlobalScope) - case InstanceCounters::kCounterTypeLength: - break; - } - } +#define DUMP_COUNTER(CounterType) \ + memory_dump->CreateAllocatorDump("counter/" #CounterType) \ + ->AddScalar("object_count", MemoryAllocatorDump::kUnitsObjects, \ + InstanceCounters::CounterValue( \ + InstanceCounters::k##CounterType##Counter)); + INSTANCE_COUNTERS_LIST(DUMP_COUNTER) return true; }
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 index 8b551d2..80cba1e0 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -1026,6 +1026,7 @@ // enabled since they're a feature always supported by Chrome. { name: "TouchEventFeatureDetection", + origin_trial_feature_name: "ForceTouchEventFeatureDetectionForInspector", status: "stable", }, // This is set conditionally in SetRuntimeFeaturesDefaultsAndUpdateFromArgs
diff --git a/third_party/WebKit/Source/platform/bindings/ScriptState.h b/third_party/WebKit/Source/platform/bindings/ScriptState.h index ff29914..e2e75ee 100644 --- a/third_party/WebKit/Source/platform/bindings/ScriptState.h +++ b/third_party/WebKit/Source/platform/bindings/ScriptState.h
@@ -97,26 +97,22 @@ return From(isolate->GetCurrentContext()); } - static ScriptState* ForFunctionObject( + static ScriptState* ForCurrentRealm( const v8::FunctionCallbackInfo<v8::Value>& info) { - // We're assuming that the current context is not yet changed since - // the callback function has got called back. - // TODO(yukishiino): Once info.GetFunctionContext() gets implemented, - // we should use it instead. return From(info.GetIsolate()->GetCurrentContext()); } - static ScriptState* ForReceiverObject( + static ScriptState* ForRelevantRealm( const v8::FunctionCallbackInfo<v8::Value>& info) { return From(info.Holder()->CreationContext()); } - static ScriptState* ForReceiverObject( + static ScriptState* ForRelevantRealm( const v8::PropertyCallbackInfo<v8::Value>& info) { return From(info.Holder()->CreationContext()); } - static ScriptState* ForReceiverObject( + static ScriptState* ForRelevantRealm( const v8::PropertyCallbackInfo<void>& info) { return From(info.Holder()->CreationContext()); }
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp index bf8b998a..8d1c7878 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
@@ -734,9 +734,10 @@ TransformPaintPropertyNode::CreateScrollTranslation( TransformPaintPropertyNode::Root(), TransformationMatrix().Translate(7, 9), FloatPoint3D(), false, 0, - kCompositingReasonNone, expected_compositor_element_id, - ScrollPaintPropertyNode::Root(), IntSize(11, 13), IntSize(27, 31), - true, false, 0 /* mainThreadScrollingReasons */, &scroll_client); + kCompositingReasonNone, ScrollPaintPropertyNode::Root(), IntPoint(), + IntSize(11, 13), IntSize(27, 31), true, false, + 0 /* mainThreadScrollingReasons */, expected_compositor_element_id, + &scroll_client); TestPaintArtifact artifact; artifact @@ -792,9 +793,9 @@ TransformPaintPropertyNode::CreateScrollTranslation( TransformPaintPropertyNode::Root(), TransformationMatrix().Translate(7, 9), FloatPoint3D(), false, 0, - kCompositingReasonNone, CompositorElementId(), - ScrollPaintPropertyNode::Root(), IntSize(11, 13), IntSize(27, 31), - true, false, 0 /* mainThreadScrollingReasons */, nullptr); + kCompositingReasonNone, ScrollPaintPropertyNode::Root(), IntPoint(), + IntSize(11, 13), IntSize(27, 31), true, false, + 0 /* mainThreadScrollingReasons */, CompositorElementId(), nullptr); RefPtr<TransformPaintPropertyNode> transform = TransformPaintPropertyNode::Create( @@ -840,19 +841,19 @@ TransformPaintPropertyNode::Root(), TransformationMatrix().Translate(11, 13), FloatPoint3D(), false, 0, kCompositingReasonLayerForScrollingContents, - expected_compositor_element_id_a, ScrollPaintPropertyNode::Root(), - IntSize(2, 3), IntSize(5, 7), false, true, + ScrollPaintPropertyNode::Root(), IntPoint(), IntSize(2, 3), + IntSize(5, 7), false, true, MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects, - nullptr); + expected_compositor_element_id_a, nullptr); CompositorElementId expected_compositor_element_id_b = CompositorElementId(3); RefPtr<TransformPaintPropertyNode> scroll_translation_b = TransformPaintPropertyNode::CreateScrollTranslation( scroll_translation_a, TransformationMatrix().Translate(37, 41), FloatPoint3D(), false, 0, kCompositingReasonNone, - expected_compositor_element_id_b, scroll_translation_a->ScrollNode(), - IntSize(19, 23), IntSize(29, 31), true, false, - 0 /* mainThreadScrollingReasons */, nullptr); + scroll_translation_a->ScrollNode(), IntPoint(), IntSize(19, 23), + IntSize(29, 31), true, false, 0 /* mainThreadScrollingReasons */, + expected_compositor_element_id_b, nullptr); TestPaintArtifact artifact; artifact.Chunk(scroll_translation_a, ClipPaintPropertyNode::Root(), effect) .RectDrawing(FloatRect(7, 11, 13, 17), Color::kWhite);
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp index b35de4a9..5edac71e 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp +++ b/third_party/WebKit/Source/platform/graphics/compositing/PropertyTreeManager.cpp
@@ -275,7 +275,8 @@ int transform_node_id = EnsureCompositorTransformNode(scroll_offset_node); auto& compositor_transform_node = *GetTransformTree().Node(transform_node_id); - auto compositor_element_id = scroll_offset_node->GetCompositorElementId(); + auto compositor_element_id = + scroll_offset_node->ScrollNode()->GetCompositorElementId(); if (compositor_element_id) { compositor_scroll_node.element_id = compositor_element_id; property_trees_.element_id_to_scroll_node_index[compositor_element_id] = @@ -304,8 +305,8 @@ void PropertyTreeManager::UpdateLayerScrollMapping( cc::Layer* layer, const TransformPaintPropertyNode* transform) { - auto* enclosing_scroll_node = transform->FindEnclosingScrollNode(); - int scroll_node_id = EnsureCompositorScrollNode(enclosing_scroll_node); + auto* scroll_node = transform->FindEnclosingScrollNode(); + int scroll_node_id = EnsureCompositorScrollNode(scroll_node); layer->SetScrollTreeIndex(scroll_node_id); auto& compositor_scroll_node = *GetScrollTree().Node(scroll_node_id); @@ -316,14 +317,14 @@ *GetTransformTree().Node(compositor_scroll_node.transform_id); // TODO(pdr): Set this in updateScrollAndScrollTranslationNodes once the // layer id is no longer needed. - GetScrollTree().SetScrollOffset(transform->GetCompositorElementId(), + GetScrollTree().SetScrollOffset(scroll_node->GetCompositorElementId(), compositor_transform_node.scroll_offset); // TODO(pdr): This approach of setting a callback on all Layers with a scroll // node is wrong because only the base scrollable layer needs this callback. // This should be fixed as part of correctly creating scrollable layers in // https://crbug.com/738613. - if (auto* scroll_client = enclosing_scroll_node->ScrollClient()) { + if (auto* scroll_client = scroll_node->ScrollClient()) { layer->set_did_scroll_callback( base::Bind(&blink::WebLayerScrollClient::DidScroll, base::Unretained(scroll_client)));
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeState.cpp b/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeState.cpp index 9ebee1f..982da4d 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeState.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/PropertyTreeState.cpp
@@ -35,6 +35,13 @@ if (Transform()->GetCompositorElementId() && !element_ids.Contains(Transform()->GetCompositorElementId())) return Transform()->GetCompositorElementId(); + // TODO(pdr): This should be removed when scroll element ids are used only + // for scroll layers. + if (auto* scroll_node = Transform()->ScrollNode()) { + if (scroll_node->GetCompositorElementId() && + !element_ids.Contains(scroll_node->GetCompositorElementId())) + return scroll_node->GetCompositorElementId(); + } return CompositorElementId(); }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.cpp b/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.cpp index 9038b18..b26ac753 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.cpp
@@ -9,10 +9,10 @@ namespace blink { ScrollPaintPropertyNode* ScrollPaintPropertyNode::Root() { - DEFINE_STATIC_REF( - ScrollPaintPropertyNode, root, - (ScrollPaintPropertyNode::Create(nullptr, IntSize(), IntSize(), false, - false, 0, nullptr))); + DEFINE_STATIC_REF(ScrollPaintPropertyNode, root, + (ScrollPaintPropertyNode::Create( + nullptr, IntPoint(), IntSize(), IntSize(), false, false, + 0, CompositorElementId(), nullptr))); return root; } @@ -20,6 +20,8 @@ StringBuilder text; text.Append("parent="); text.Append(String::Format("%p", Parent())); + text.Append(" bounds_offset="); + text.Append(bounds_offset_.ToString()); text.Append(" container_bounds="); text.Append(container_bounds_.ToString()); text.Append(" bounds="); @@ -41,6 +43,8 @@ } else { text.Append("none"); } + text.Append(String::Format(" compositorElementId=%s", + compositor_element_id_.ToString().c_str())); if (scroll_client_) text.Append(String::Format(" scrollClient=%p", scroll_client_)); return text.ToString();
diff --git a/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.h index 6b762d6..e9006c8 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.h +++ b/third_party/WebKit/Source/platform/graphics/paint/ScrollPaintPropertyNode.h
@@ -6,7 +6,9 @@ #define ScrollPaintPropertyNode_h #include "platform/PlatformExport.h" +#include "platform/geometry/FloatPoint.h" #include "platform/geometry/FloatSize.h" +#include "platform/graphics/CompositorElementId.h" #include "platform/graphics/paint/PaintPropertyNode.h" #include "platform/scroll/MainThreadScrollingReason.h" #include "platform/wtf/text/WTFString.h" @@ -38,44 +40,55 @@ static PassRefPtr<ScrollPaintPropertyNode> Create( PassRefPtr<const ScrollPaintPropertyNode> parent, + const IntPoint& bounds_offset, const IntSize& container_bounds, const IntSize& bounds, bool user_scrollable_horizontal, bool user_scrollable_vertical, MainThreadScrollingReasons main_thread_scrolling_reasons, + CompositorElementId compositor_element_id, WebLayerScrollClient* scroll_client) { return AdoptRef(new ScrollPaintPropertyNode( - std::move(parent), container_bounds, bounds, user_scrollable_horizontal, - user_scrollable_vertical, main_thread_scrolling_reasons, - scroll_client)); + std::move(parent), bounds_offset, container_bounds, bounds, + user_scrollable_horizontal, user_scrollable_vertical, + main_thread_scrolling_reasons, compositor_element_id, scroll_client)); } bool Update(PassRefPtr<const ScrollPaintPropertyNode> parent, + const IntPoint& bounds_offset, const IntSize& container_bounds, const IntSize& bounds, bool user_scrollable_horizontal, bool user_scrollable_vertical, MainThreadScrollingReasons main_thread_scrolling_reasons, + CompositorElementId compositor_element_id, WebLayerScrollClient* scroll_client) { bool parent_changed = PaintPropertyNode::Update(std::move(parent)); - if (container_bounds == container_bounds_ && bounds == bounds_ && + if (bounds_offset == bounds_offset_ && + container_bounds == container_bounds_ && bounds == bounds_ && user_scrollable_horizontal == user_scrollable_horizontal_ && user_scrollable_vertical == user_scrollable_vertical_ && main_thread_scrolling_reasons == main_thread_scrolling_reasons_ && + compositor_element_id_ == compositor_element_id && scroll_client == scroll_client_) return parent_changed; SetChanged(); + bounds_offset_ = bounds_offset; container_bounds_ = container_bounds; bounds_ = bounds; user_scrollable_horizontal_ = user_scrollable_horizontal; user_scrollable_vertical_ = user_scrollable_vertical; main_thread_scrolling_reasons_ = main_thread_scrolling_reasons; + compositor_element_id_ = compositor_element_id; scroll_client_ = scroll_client; return true; } + // Offset for |ContainerBounds| and |Bounds|. + const IntPoint& Offset() const { return bounds_offset_; } + // Size of the container area that the contents scrolls in, not including // non-overlay scrollbars. Overlay scrollbars do not affect these bounds. const IntSize& ContainerBounds() const { return container_bounds_; } @@ -103,6 +116,10 @@ MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects; } + const CompositorElementId& GetCompositorElementId() const { + return compositor_element_id_; + } + WebLayerScrollClient* ScrollClient() const { return scroll_client_; } #if DCHECK_IS_ON() @@ -111,8 +128,9 @@ PassRefPtr<ScrollPaintPropertyNode> Clone() const { RefPtr<ScrollPaintPropertyNode> cloned = AdoptRef(new ScrollPaintPropertyNode( - Parent(), container_bounds_, bounds_, user_scrollable_horizontal_, - user_scrollable_vertical_, main_thread_scrolling_reasons_, + Parent(), bounds_offset_, container_bounds_, bounds_, + user_scrollable_horizontal_, user_scrollable_vertical_, + main_thread_scrolling_reasons_, compositor_element_id_, scroll_client_)); return cloned; } @@ -120,11 +138,12 @@ // The equality operator is used by FindPropertiesNeedingUpdate.h for checking // if a scroll node has changed. bool operator==(const ScrollPaintPropertyNode& o) const { - return Parent() == o.Parent() && container_bounds_ == o.container_bounds_ && - bounds_ == o.bounds_ && + return Parent() == o.Parent() && bounds_offset_ == o.bounds_offset_ && + container_bounds_ == o.container_bounds_ && bounds_ == o.bounds_ && user_scrollable_horizontal_ == o.user_scrollable_horizontal_ && user_scrollable_vertical_ == o.user_scrollable_vertical_ && main_thread_scrolling_reasons_ == o.main_thread_scrolling_reasons_ && + compositor_element_id_ == o.compositor_element_id_ && scroll_client_ == o.scroll_client_; } @@ -136,25 +155,33 @@ private: ScrollPaintPropertyNode( PassRefPtr<const ScrollPaintPropertyNode> parent, + IntPoint bounds_offset, IntSize container_bounds, IntSize bounds, bool user_scrollable_horizontal, bool user_scrollable_vertical, MainThreadScrollingReasons main_thread_scrolling_reasons, + CompositorElementId compositor_element_id, WebLayerScrollClient* scroll_client) : PaintPropertyNode(std::move(parent)), + bounds_offset_(bounds_offset), container_bounds_(container_bounds), bounds_(bounds), user_scrollable_horizontal_(user_scrollable_horizontal), user_scrollable_vertical_(user_scrollable_vertical), main_thread_scrolling_reasons_(main_thread_scrolling_reasons), + compositor_element_id_(compositor_element_id), scroll_client_(scroll_client) {} + IntPoint bounds_offset_; IntSize container_bounds_; IntSize bounds_; bool user_scrollable_horizontal_ : 1; bool user_scrollable_vertical_ : 1; MainThreadScrollingReasons main_thread_scrolling_reasons_; + // The scrolling element id is stored directly on the scroll node and not on + // the associated TransformPaintPropertyNode used for scroll offset. + CompositorElementId compositor_element_id_; WebLayerScrollClient* scroll_client_; };
diff --git a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h index a8d0393..ef02f33c 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h +++ b/third_party/WebKit/Source/platform/graphics/paint/TransformPaintPropertyNode.h
@@ -56,23 +56,28 @@ bool flattens_inherited_transform, unsigned rendering_context_id, CompositingReasons direct_compositing_reasons, - const CompositorElementId& compositor_element_id, PassRefPtr<const ScrollPaintPropertyNode> parent_scroll, + const IntPoint& bounds_offset, const IntSize& scroll_container_bounds, const IntSize& bounds, bool user_scrollable_horizontal, bool user_scrollable_vertical, MainThreadScrollingReasons main_thread_scrolling_reasons, + const CompositorElementId& compositor_element_id, WebLayerScrollClient* scroll_client) { // If this transform is for scroll offset, it should be a 2d translation. DCHECK(matrix.IsIdentityOr2DTranslation()); return AdoptRef(new TransformPaintPropertyNode( std::move(parent), matrix, origin, flattens_inherited_transform, - rendering_context_id, direct_compositing_reasons, compositor_element_id, + rendering_context_id, direct_compositing_reasons, + // The compositor element id is empty because the element id is stored + // on the scroll node. + CompositorElementId(), ScrollPaintPropertyNode::Create( - std::move(parent_scroll), scroll_container_bounds, bounds, - user_scrollable_horizontal, user_scrollable_vertical, - main_thread_scrolling_reasons, scroll_client))); + std::move(parent_scroll), bounds_offset, scroll_container_bounds, + bounds, user_scrollable_horizontal, user_scrollable_vertical, + main_thread_scrolling_reasons, compositor_element_id, + scroll_client))); } bool Update( @@ -109,23 +114,24 @@ bool flattens_inherited_transform, unsigned rendering_context_id, CompositingReasons direct_compositing_reasons, - CompositorElementId compositor_element_id, PassRefPtr<const ScrollPaintPropertyNode> parent_scroll, + const IntPoint& bounds_offset, const IntSize& scroll_container_bounds, const IntSize& bounds, bool user_scrollable_horizontal, bool user_scrollable_vertical, MainThreadScrollingReasons main_thread_scrolling_reasons, + CompositorElementId compositor_element_id, WebLayerScrollClient* scroll_client) { bool changed = Update(std::move(parent), matrix, origin, flattens_inherited_transform, rendering_context_id, - direct_compositing_reasons, compositor_element_id); + direct_compositing_reasons, CompositorElementId()); DCHECK(scroll_); DCHECK(matrix.IsIdentityOr2DTranslation()); changed |= scroll_->Update( - std::move(parent_scroll), scroll_container_bounds, bounds, - user_scrollable_horizontal, user_scrollable_vertical, - main_thread_scrolling_reasons, scroll_client); + std::move(parent_scroll), bounds_offset, scroll_container_bounds, + bounds, user_scrollable_horizontal, user_scrollable_vertical, + main_thread_scrolling_reasons, compositor_element_id, scroll_client); return changed; }
diff --git a/tools/mb/mb.py b/tools/mb/mb.py index 2b93458..6905bcc 100755 --- a/tools/mb/mb.py +++ b/tools/mb/mb.py
@@ -888,17 +888,6 @@ command, extra_files = self.GetIsolateCommand(target, vals) runtime_deps = self.ReadFile(runtime_deps_path).splitlines() - if android: - # TODO(hzl): Rewrite the following lib.unstripped logic. - # crbug.com/749283 - unstripped_libs = [] - for f in runtime_deps: - if f.endswith('.so'): - if os.path.isfile(self.PathJoin(self.ToAbsPath(build_dir), - 'lib.unstripped', - os.path.basename(f))): - unstripped_libs.append('lib.unstripped/%s' % os.path.basename(f)) - runtime_deps.extend(unstripped_libs) self.WriteIsolateFiles(build_dir, command, target, runtime_deps, extra_files)
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index b1de6ee..039bdd5 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -103,6 +103,7 @@ 'Browser Side Navigation Linux': 'release_bot', 'CFI Linux CF': 'cfi_full_cfi_diag_recover_release_static', 'CFI Linux ToT': 'clang_tot_cfi_full_cfi_diag_thin_lto_release_static_dcheck_always_on', + 'ChromeOS amd64 Chromium Goma Canary': 'cros_chrome_sdk', 'Chromium Linux Goma Canary': 'release_bot', 'Chromium Linux Goma Canary': 'release_bot', 'Chromium Linux Goma Canary (clobber)': 'release_bot',
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index d337605..97018e6 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -33735,6 +33735,16 @@ <int value="2" label="All"/> </enum> +<enum name="ServiceWorkerInstalledScriptsManager.FinishedReason"> + <int value="0" label="NOT_FINISHED"/> + <int value="1" label="SUCCESS"/> + <int value="2" label="NO_HTTP_INFO_ERROR"/> + <int value="3" label="CREATE_DATA_PIPE_ERROR"/> + <int value="4" label="CONNECTION_ERROR"/> + <int value="5" label="RESPONSE_READER_ERROR"/> + <int value="6" label="META_DATA_SENDER_ERROR"/> +</enum> + <enum name="ServiceWorkerMetrics.EventType"> <int value="0" label="ACTIVATE"/> <int value="1" label="INSTALL"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 435ab9e..9bba6d1 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -64762,6 +64762,17 @@ </summary> </histogram> +<histogram + name="ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable" + units="requests"> + <owner>devdeepray@chromium.org</owner> + <owner>tbansal@chromium.org</owner> + <summary> + Records the number of delayable requests in-flight when a non-delayable + request is started. + </summary> +</histogram> + <histogram name="ResourceScheduler.NumSkippedScans.ScheduleStart" units="requests"> <owner>csharrison@chromium.org</owner> @@ -71201,6 +71212,17 @@ </summary> </histogram> +<histogram name="ServiceWorker.StartWorker.InstalledScriptsSender.Status" + enum="ServiceWorkerInstalledScriptsManager.FinishedReason"> + <owner>shimazu@chromium.org</owner> + <summary> + The result of sending installed scripts over + ServiceWorkerInstalledScriptsSender. This is recorded after every start + worker attempt that sent the scripts through + ServiceWorkerInstalledScriptsSender. + </summary> +</histogram> + <histogram name="ServiceWorker.StartWorker.Purpose" enum="ServiceWorkerMetrics.EventType"> <owner>falken@chromium.org</owner>
diff --git a/tools/perf/page_sets/data/loading_mobile.json b/tools/perf/page_sets/data/loading_mobile.json index bfda028..b364e63 100644 --- a/tools/perf/page_sets/data/loading_mobile.json +++ b/tools/perf/page_sets/data/loading_mobile.json
@@ -1,160 +1,160 @@ { "archives": { "Facebook": { - "DEFAULT": "loading_mobile_002.wpr" + "DEFAULT": "loading_mobile_002.wprgo" }, "http://enquiry.indianrail.gov.in/mntes/MntesServlet?action=MainMenu&subAction=excep&excpType=EC": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://g1.globo.com/politica/noticia/2016/02/maioria-do-stf-autoriza-fisco-obter-dados-bancarios-sem-decisao-judicial.html": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://m.kapanlagi.com/lirik/artis/anji/kata_siapa/": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://m.kaskus.co.id/thread/57a03a3214088d91068b4567/inilah-akibat-bersikap-overprotektif-terhadap-anak/?ref=homelanding&med=hot_thread": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://m.tribunnews.com/superskor/2016/08/03/ribuan-polisi-dikerahkan-mengawal-bonek": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://news.yahoo.com/were-top-10-most-visited-us-national-parks-105323727.html": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://noticias.bol.uol.com.br/ultimas-noticias/brasil/2016/08/03/tufao-nida-nao-deixa-vitimas-mas-prejuizos-de-us-43-milhoes.htm": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://olx.co.id/iklan/iphone-6s-64-rose-gold-warna-favorite-IDiSdm5.html#5310a118c3;promoted": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.163.com": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.58pic.com": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.amazon.com/gp/aw/s/ref=is_s/189-8585431-1246432?k=shoes": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.bradesco.com.br": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.dailymotion.com/video/x3d1kj5_fallout-4-review_videogames": { - "DEFAULT": "loading_mobile_001.wpr" + "DEFAULT": "loading_mobile_001.wprgo" }, "http://www.dawn.com": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.dramaq.com.tw": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.ebs.in": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.francetvinfo.fr": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.futura-sciences.com": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.gfk.com": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.gsshop.com": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.hashocean.com": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.hongkiat.com": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.ibicn.com": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.localmoxie.com": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.locanto.in": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.mlsmatrix.com": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.sbs.co.kr": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.slideshare.net": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.thairath.co.th": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://www.thestar.com.my": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "http://xw.qq.com/news/20160803025029/NEW2016080302502901": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://2048-opera-pwa.surge.sh/": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://andreasbovens.github.io/inbox-attack/": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://dev.opera.com/": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://en.m.wikipedia.org/wiki/Solo_Foods": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://flipboard.com/topic/yoga": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://guitar-tuner.appspot.com": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://jakearchibald.github.io/trained-to-thrill/": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://m.baidu.com/s?word=%E9%B2%9C%E8%8A%B1%E9%80%9F%E9%80%92&oq=%E9%B2%9C%E8%8A%B1": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://m.facebook.com/?soft=messages": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://mobile.twitter.com/scottjehl/status/760618697727803394": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://smp.suumo.jp/mansion/tokyo/sc_104/cond/?moreCond=1": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://townwork.net": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://voice-memos.appspot.com": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://www.flipkart.com/big-wing-casuals/p/itmemeageyfn6m9z?lid=LSTSHOEMEAGURG2PHPW18FTBN&pid=SHOEMEAGURG2PHPW": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://www.google.co.id/#q=pengiriman+bunga": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://www.google.co.in/search?q=%E0%A4%AB%E0%A5%82%E0%A4%B2&rct=j#q=%E0%A4%AB%E0%A5%82%E0%A4%B2+%E0%A4%B5%E0%A4%BF%E0%A4%A4%E0%A4%B0%E0%A4%A3": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://www.google.com.br/search?q=flor#q=Entrega+de+flores&start=10": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://www.google.com/search?q=flower#q=flower+delivery": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://www.pokedex.org/": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" }, "https://www.youtube.com/watch?v=MU3YuvNRhVY": { - "DEFAULT": "loading_mobile_000.wpr" + "DEFAULT": "loading_mobile_000.wprgo" } }, "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.",
diff --git a/tools/perf/page_sets/data/loading_mobile_000.wpr.sha1 b/tools/perf/page_sets/data/loading_mobile_000.wpr.sha1 deleted file mode 100644 index 1f86156..0000000 --- a/tools/perf/page_sets/data/loading_mobile_000.wpr.sha1 +++ /dev/null
@@ -1 +0,0 @@ -2f813dcad04f48b714e168f76780c475002e02de \ No newline at end of file
diff --git a/tools/perf/page_sets/data/loading_mobile_000.wprgo.sha1 b/tools/perf/page_sets/data/loading_mobile_000.wprgo.sha1 new file mode 100644 index 0000000..60484a30 --- /dev/null +++ b/tools/perf/page_sets/data/loading_mobile_000.wprgo.sha1
@@ -0,0 +1 @@ +1534b58ad47db012eec3d047ad6c36b288c9179f \ No newline at end of file
diff --git a/tools/perf/page_sets/data/loading_mobile_001.wpr.sha1 b/tools/perf/page_sets/data/loading_mobile_001.wpr.sha1 deleted file mode 100644 index 6a84ec0..0000000 --- a/tools/perf/page_sets/data/loading_mobile_001.wpr.sha1 +++ /dev/null
@@ -1 +0,0 @@ -eb42dee8bb1223caa90efd7de715dfbf71ee322f \ No newline at end of file
diff --git a/tools/perf/page_sets/data/loading_mobile_001.wprgo.sha1 b/tools/perf/page_sets/data/loading_mobile_001.wprgo.sha1 new file mode 100644 index 0000000..16eeb6d --- /dev/null +++ b/tools/perf/page_sets/data/loading_mobile_001.wprgo.sha1
@@ -0,0 +1 @@ +47ef8f30d67a942e2efd6d2a42bf211f185d718e \ No newline at end of file
diff --git a/tools/perf/page_sets/data/loading_mobile_002.wpr.sha1 b/tools/perf/page_sets/data/loading_mobile_002.wpr.sha1 deleted file mode 100644 index ecb4104..0000000 --- a/tools/perf/page_sets/data/loading_mobile_002.wpr.sha1 +++ /dev/null
@@ -1 +0,0 @@ -9c7c37e0e21f1e76eb4c20bd592eb6d78e68b888 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/loading_mobile_002.wprgo.sha1 b/tools/perf/page_sets/data/loading_mobile_002.wprgo.sha1 new file mode 100644 index 0000000..4d7e71f --- /dev/null +++ b/tools/perf/page_sets/data/loading_mobile_002.wprgo.sha1
@@ -0,0 +1 @@ +6c076e2da3110deb55a726650b4d98c42413579a \ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_desktop_053.wprgo.sha1 b/tools/perf/page_sets/data/system_health_desktop_053.wprgo.sha1 index c68c9d71..bf7b2e2a4 100644 --- a/tools/perf/page_sets/data/system_health_desktop_053.wprgo.sha1 +++ b/tools/perf/page_sets/data/system_health_desktop_053.wprgo.sha1
@@ -1 +1 @@ -fabc0f5dd6e89556c963721c40259cab2ad88c58 \ No newline at end of file +6db380ff9f059b80b785f51828c64aaa46e6c373 \ No newline at end of file
diff --git a/ui/app_list/views/app_list_view_unittest.cc b/ui/app_list/views/app_list_view_unittest.cc index 50dbb67a..e4e02a4 100644 --- a/ui/app_list/views/app_list_view_unittest.cc +++ b/ui/app_list/views/app_list_view_unittest.cc
@@ -201,6 +201,96 @@ EXPECT_FALSE(view_->GetWidget()->IsVisible()); } + void InitializeStartPageView(size_t apps_num) { + Initialize(0, false, false); + AppListTestModel* model = delegate_->GetTestModel(); + + // Adds suggestion apps to the start page view and show start page view. + for (size_t i = 0; i < apps_num; i++) + model->results()->Add(base::MakeUnique<TestStartPageSearchResult>()); + EXPECT_TRUE(SetAppListState(AppListModel::STATE_START)); + start_page_view()->UpdateForTesting(); + EXPECT_EQ(apps_num, GetVisibleViews(start_page_view()->tile_views())); + + // Initially, no view gets focus. + EXPECT_EQ(FOCUS_NONE, search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(StartPageView::kNoSelection, + start_page_view()->GetSelectedIndexForTest()); + } + + // Test focus movement within search box view and start page view on tab key + // or right arrow key. + void TestStartPageViewForwardFocusOnKey(ui::KeyEvent* key, size_t apps_num) { + // Sets focus on search box. + search_box_view()->search_box()->OnKeyEvent(key); + EXPECT_EQ(FOCUS_SEARCH_BOX, search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(StartPageView::kNoSelection, + start_page_view()->GetSelectedIndexForTest()); + + // When focus is on search box, moves focus through suggestion apps. + for (size_t i = 0; i < apps_num; i++) { + search_box_view()->search_box()->OnKeyEvent(key); + EXPECT_EQ(FOCUS_CONTENTS_VIEW, + search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(static_cast<int>(i), + start_page_view()->GetSelectedIndexForTest()); + } + + // When focus is on the last suggestion app, moves focus to expand arrow. + search_box_view()->search_box()->OnKeyEvent(key); + EXPECT_EQ(FOCUS_CONTENTS_VIEW, + search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(StartPageView::kExpandArrowSelection, + start_page_view()->GetSelectedIndexForTest()); + + // When focus is on expand arrow, clears focus. + search_box_view()->search_box()->OnKeyEvent(key); + EXPECT_EQ(FOCUS_NONE, search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(StartPageView::kNoSelection, + start_page_view()->GetSelectedIndexForTest()); + } + + // Test focus movement within search box view and start page view on shift+tab + // key or left arrow key. + void TestStartPageViewBackwardFocusOnKey(ui::KeyEvent* key, size_t apps_num) { + // Sets focus on expand arrow. + search_box_view()->search_box()->OnKeyEvent(key); + EXPECT_EQ(FOCUS_CONTENTS_VIEW, + search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(StartPageView::kExpandArrowSelection, + start_page_view()->GetSelectedIndexForTest()); + + // When focus is on search box, moves focus through suggestion apps + // reversely. + for (size_t i = 0; i < apps_num; i++) { + search_box_view()->search_box()->OnKeyEvent(key); + EXPECT_EQ(FOCUS_CONTENTS_VIEW, + search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(static_cast<int>(apps_num - 1 - i), + start_page_view()->GetSelectedIndexForTest()); + } + + // When focus is on the first suggestion app, moves focus to search box. + search_box_view()->search_box()->OnKeyEvent(key); + EXPECT_EQ(FOCUS_SEARCH_BOX, search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(StartPageView::kNoSelection, + start_page_view()->GetSelectedIndexForTest()); + + // When focus is on search box, clears focus. + search_box_view()->search_box()->OnKeyEvent(key); + EXPECT_EQ(FOCUS_NONE, search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(StartPageView::kNoSelection, + start_page_view()->GetSelectedIndexForTest()); + } + + AppListMainView* main_view() { return view_->app_list_main_view(); } + + StartPageView* start_page_view() { + return main_view()->contents_view()->start_page_view(); + } + + SearchBoxView* search_box_view() { return main_view()->search_box_view(); } + private: base::test::ScopedFeatureList scoped_feature_list_; DISALLOW_COPY_AND_ASSIGN(AppListViewFullscreenTest); @@ -388,64 +478,110 @@ } // Tests the focus change in search box view and start page view triggered by -// tab key . +// tab key. TEST_F(AppListViewFullscreenTest, StartPageTabFocusTest) { - Initialize(0, false, false); - AppListTestModel* model = delegate_->GetTestModel(); - AppListMainView* main_view = view_->app_list_main_view(); - StartPageView* start_page_view = - main_view->contents_view()->start_page_view(); - SearchBoxView* search_box_view = main_view->search_box_view(); - - // Adds 3 suggestion apps to the start page view and show start page view. - constexpr size_t apps_num = 3; - for (size_t i = 0; i < apps_num; i++) - model->results()->Add(base::MakeUnique<TestStartPageSearchResult>()); - EXPECT_TRUE(SetAppListState(AppListModel::STATE_START)); - start_page_view->UpdateForTesting(); - EXPECT_EQ(apps_num, GetVisibleViews(start_page_view->tile_views())); - - // Initially, no view gets focus. - EXPECT_EQ(FOCUS_NONE, search_box_view->get_focused_view_for_test()); - EXPECT_EQ(StartPageView::kNoSelection, - start_page_view->GetSelectedIndexForTest()); - - // Hitting tab key sets focus on search box. + constexpr size_t apps_num = 5u; + InitializeStartPageView(apps_num); ui::KeyEvent tab(ui::ET_KEY_PRESSED, ui::VKEY_TAB, ui::EF_NONE); - search_box_view->search_box()->OnKeyEvent(&tab); - EXPECT_EQ(FOCUS_SEARCH_BOX, search_box_view->get_focused_view_for_test()); - EXPECT_EQ(StartPageView::kNoSelection, - start_page_view->GetSelectedIndexForTest()); + TestStartPageViewForwardFocusOnKey(&tab, apps_num); +} - // Hitting tab key when focus is on search box moves focus through suggestion - // apps. - for (size_t i = 0; i < apps_num; i++) { - search_box_view->search_box()->OnKeyEvent(&tab); - EXPECT_EQ(FOCUS_CONTENTS_VIEW, - search_box_view->get_focused_view_for_test()); - EXPECT_EQ(static_cast<int>(i), start_page_view->GetSelectedIndexForTest()); - } - - // Hitting tab key when focus is on the last suggestion app moves focus to - // expand arrow view. - search_box_view->search_box()->OnKeyEvent(&tab); - EXPECT_EQ(FOCUS_CONTENTS_VIEW, search_box_view->get_focused_view_for_test()); - EXPECT_EQ(StartPageView::kExpandArrowSelection, - start_page_view->GetSelectedIndexForTest()); - - // Hitting tab key when focus is on the expand arrow view clears focus. - search_box_view->search_box()->OnKeyEvent(&tab); - EXPECT_EQ(FOCUS_NONE, search_box_view->get_focused_view_for_test()); - EXPECT_EQ(StartPageView::kNoSelection, - start_page_view->GetSelectedIndexForTest()); - - // Hitting shift-tab key when no view gets focus sets focus to the expand - // arrow view. +// Tests the focus change in search box view and start page view triggered by +// shift+tab key. +TEST_F(AppListViewFullscreenTest, StartPageShiftTabFocusTest) { + constexpr size_t apps_num = 5u; + InitializeStartPageView(apps_num); ui::KeyEvent shift_tab(ui::ET_KEY_PRESSED, ui::VKEY_TAB, ui::EF_SHIFT_DOWN); - search_box_view->search_box()->OnKeyEvent(&shift_tab); - EXPECT_EQ(FOCUS_CONTENTS_VIEW, search_box_view->get_focused_view_for_test()); + TestStartPageViewBackwardFocusOnKey(&shift_tab, apps_num); +} + +// Tests the focus change in search box view and start page view triggered by +// right arrow key. +TEST_F(AppListViewFullscreenTest, StartPageRightArrowFocusTest) { + constexpr size_t apps_num = 5u; + InitializeStartPageView(apps_num); + ui::KeyEvent right(ui::ET_KEY_PRESSED, ui::VKEY_RIGHT, ui::EF_NONE); + TestStartPageViewForwardFocusOnKey(&right, apps_num); +} + +// Tests the focus change in search box view and start page view triggered by +// left arrow key. +TEST_F(AppListViewFullscreenTest, StartPageLeftArrowFocusTest) { + constexpr size_t apps_num = 5u; + InitializeStartPageView(apps_num); + ui::KeyEvent left(ui::ET_KEY_PRESSED, ui::VKEY_LEFT, ui::EF_NONE); + TestStartPageViewBackwardFocusOnKey(&left, apps_num); +} + +// Tests the focus change in search box view and start page view triggered by +// down arrow key. +TEST_F(AppListViewFullscreenTest, StartPageDownArrowFocusTest) { + constexpr size_t apps_num = 5u; + InitializeStartPageView(apps_num); + + // Hitting down key sets focus on search box. + ui::KeyEvent down(ui::ET_KEY_PRESSED, ui::VKEY_DOWN, ui::EF_NONE); + search_box_view()->search_box()->OnKeyEvent(&down); + EXPECT_EQ(FOCUS_SEARCH_BOX, search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(StartPageView::kNoSelection, + start_page_view()->GetSelectedIndexForTest()); + + // Hitting down key when focus is on search box moves focus to the suggestion + // app in the middle. + search_box_view()->search_box()->OnKeyEvent(&down); + EXPECT_EQ(FOCUS_CONTENTS_VIEW, + search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(static_cast<int>(apps_num / 2), + start_page_view()->GetSelectedIndexForTest()); + + // Hitting down key when focus is on suggestion app moves focus to expand + // arrow. + search_box_view()->search_box()->OnKeyEvent(&down); + EXPECT_EQ(FOCUS_CONTENTS_VIEW, + search_box_view()->get_focused_view_for_test()); EXPECT_EQ(StartPageView::kExpandArrowSelection, - start_page_view->GetSelectedIndexForTest()); + start_page_view()->GetSelectedIndexForTest()); + + // Hitting down key when focus is on expand arrow clears focus. + search_box_view()->search_box()->OnKeyEvent(&down); + EXPECT_EQ(FOCUS_NONE, search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(StartPageView::kNoSelection, + start_page_view()->GetSelectedIndexForTest()); +} + +// Tests the focus change in search box view and start page view triggered by +// up arrow key. +TEST_F(AppListViewFullscreenTest, StartPageUpArrowFocusTest) { + constexpr size_t apps_num = 5u; + InitializeStartPageView(apps_num); + + // Hitting up key sets focus on expand arrow. + ui::KeyEvent up(ui::ET_KEY_PRESSED, ui::VKEY_UP, ui::EF_NONE); + search_box_view()->search_box()->OnKeyEvent(&up); + EXPECT_EQ(FOCUS_CONTENTS_VIEW, + search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(StartPageView::kExpandArrowSelection, + start_page_view()->GetSelectedIndexForTest()); + + // Hitting up key when focus is on expand arrow moves focus to the suggestion + // app in the middle. + search_box_view()->search_box()->OnKeyEvent(&up); + EXPECT_EQ(FOCUS_CONTENTS_VIEW, + search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(static_cast<int>(apps_num / 2), + start_page_view()->GetSelectedIndexForTest()); + + // Hitting up key when focus is on suggestion app moves focus to search box. + search_box_view()->search_box()->OnKeyEvent(&up); + EXPECT_EQ(FOCUS_SEARCH_BOX, search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(StartPageView::kNoSelection, + start_page_view()->GetSelectedIndexForTest()); + + // Hitting up key when focus is on search box clears focus. + search_box_view()->search_box()->OnKeyEvent(&up); + EXPECT_EQ(FOCUS_NONE, search_box_view()->get_focused_view_for_test()); + EXPECT_EQ(StartPageView::kNoSelection, + start_page_view()->GetSelectedIndexForTest()); } // Tests displaying the app list and performs a standard set of checks on its
diff --git a/ui/app_list/views/contents_view.cc b/ui/app_list/views/contents_view.cc index 62eae1c1..a35775d 100644 --- a/ui/app_list/views/contents_view.cc +++ b/ui/app_list/views/contents_view.cc
@@ -504,10 +504,14 @@ bool ContentsView::OnKeyPressed(const ui::KeyEvent& event) { if (app_list_pages_[GetActivePageIndex()]->OnKeyPressed(event)) return true; - if (event.key_code() != ui::VKEY_TAB) + if (event.key_code() != ui::VKEY_TAB && + !GetSearchBoxView()->IsArrowKey(event)) return false; if (is_fullscreen_app_list_enabled_) { - GetSearchBoxView()->MoveTabFocus(event.IsShiftDown()); + if (event.key_code() == ui::VKEY_TAB) + GetSearchBoxView()->MoveTabFocus(event.IsShiftDown()); + else + GetSearchBoxView()->MoveArrowFocus(event); return true; } if (event.IsShiftDown()) {
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc index 4836d28..7f3f7a05 100644 --- a/ui/app_list/views/search_box_view.cc +++ b/ui/app_list/views/search_box_view.cc
@@ -288,6 +288,41 @@ return static_cast<views::ImageButton*>(close_button_); } +bool SearchBoxView::MoveArrowFocus(const ui::KeyEvent& event) { + DCHECK(IsArrowKey(event)); + DCHECK(is_fullscreen_app_list_enabled_); + + // Left and right arrow should work in the same way as shift+tab and tab. + if (event.key_code() == ui::VKEY_LEFT) + return MoveTabFocus(true); + if (event.key_code() == ui::VKEY_RIGHT) + return MoveTabFocus(false); + if (back_button_) + back_button_->SetSelected(false); + if (close_button_) + close_button_->SetSelected(false); + const bool move_up = event.key_code() == ui::VKEY_UP; + + switch (focused_view_) { + case FOCUS_NONE: + focused_view_ = move_up ? FOCUS_CONTENTS_VIEW : FOCUS_SEARCH_BOX; + break; + case FOCUS_BACK_BUTTON: + case FOCUS_SEARCH_BOX: + case FOCUS_CLOSE_BUTTON: + focused_view_ = move_up ? FOCUS_NONE : FOCUS_CONTENTS_VIEW; + break; + case FOCUS_CONTENTS_VIEW: + focused_view_ = move_up ? FOCUS_SEARCH_BOX : FOCUS_NONE; + break; + default: + NOTREACHED(); + } + + SetSelected(focused_view_ == FOCUS_SEARCH_BOX); + return (focused_view_ < FOCUS_CONTENTS_VIEW); +} + // Returns true if set internally, i.e. if focused_view_ != CONTENTS_VIEW. // Note: because we always want to be able to type in the edit box, this is only // a faux-focus so that buttons can respond to the ENTER key. @@ -620,6 +655,12 @@ contents_view_->layer()->SetOpacity(opacity); } +bool SearchBoxView::IsArrowKey(const ui::KeyEvent& event) { + return event.key_code() == ui::VKEY_UP || event.key_code() == ui::VKEY_DOWN || + event.key_code() == ui::VKEY_LEFT || + event.key_code() == ui::VKEY_RIGHT; +} + void SearchBoxView::UpdateModel() { // Temporarily remove from observer to ignore notifications caused by us. model_->search_box()->RemoveObserver(this); @@ -661,6 +702,10 @@ MoveTabFocus(key_event.IsShiftDown())) return true; + if (is_fullscreen_app_list_enabled_ && IsArrowKey(key_event) && + focused_view_ != FOCUS_CONTENTS_VIEW && MoveArrowFocus(key_event)) + return true; + if (focused_view_ == FOCUS_BACK_BUTTON && back_button_ && back_button_->OnKeyPressed(key_event)) return true; @@ -681,7 +726,10 @@ // If they didn't, we still select the first search item, in case they're // moving the caret through typed search text. The UP arrow never moves // focus from text/buttons to app list/results, so ignore it. - if (focused_view_ < FOCUS_CONTENTS_VIEW && + // For fullscreen app list, the arrow key should be ignored here since it + // has been handled. + if (!is_fullscreen_app_list_enabled_ && + focused_view_ < FOCUS_CONTENTS_VIEW && (key_event.key_code() == ui::VKEY_LEFT || key_event.key_code() == ui::VKEY_RIGHT || key_event.key_code() == ui::VKEY_DOWN)) {
diff --git a/ui/app_list/views/search_box_view.h b/ui/app_list/views/search_box_view.h index ea6c40d7..511e75a 100644 --- a/ui/app_list/views/search_box_view.h +++ b/ui/app_list/views/search_box_view.h
@@ -77,6 +77,9 @@ contents_view_ = contents_view; } + // Moves focus in response to arrow key. + bool MoveArrowFocus(const ui::KeyEvent& event); + // Moves focus forward/backwards in response to TAB. bool MoveTabFocus(bool move_backwards); @@ -141,6 +144,10 @@ // Whether the search box is active. bool is_search_box_active() const { return is_search_box_active_; } + // Whether the key event is an arrow up/down/left/right. + // TODO(weidongg): move this function to utility class. + static bool IsArrowKey(const ui::KeyEvent& event); + private: // Updates model text and selection model with current Textfield info. void UpdateModel();
diff --git a/ui/app_list/views/search_box_view_unittest.cc b/ui/app_list/views/search_box_view_unittest.cc index 6a7635f..d651e5c 100644 --- a/ui/app_list/views/search_box_view_unittest.cc +++ b/ui/app_list/views/search_box_view_unittest.cc
@@ -241,7 +241,13 @@ KeyPress(ui::VKEY_DOWN); EXPECT_EQ(0, GetQueryChangedCountAndReset()); - EXPECT_EQ(1, GetContentsViewKeyPressCountAndReset()); + if (test_with_fullscreen()) { + // The initial down arrow key is handled by search box in fullscreen + // app list. + EXPECT_EQ(0, GetContentsViewKeyPressCountAndReset()); + } else { + EXPECT_EQ(1, GetContentsViewKeyPressCountAndReset()); + } view()->ClearSearch(); EXPECT_EQ(1, GetQueryChangedCountAndReset());
diff --git a/ui/app_list/views/start_page_view.cc b/ui/app_list/views/start_page_view.cc index 0805d83..3ed30288 100644 --- a/ui/app_list/views/start_page_view.cc +++ b/ui/app_list/views/start_page_view.cc
@@ -303,34 +303,11 @@ } bool StartPageView::OnKeyPressed(const ui::KeyEvent& event) { + if (is_fullscreen_app_list_enabled_) + return HandleKeyPressedFullscreen(event); const int forward_dir = base::i18n::IsRTL() ? -1 : 1; int selected_index = suggestions_container_->selected_index(); - if (expand_arrow_view_ && expand_arrow_view_->selected()) { - if (expand_arrow_view_->OnKeyPressed(event)) { - expand_arrow_view_->SetSelected(false); - return true; - } - - if (event.key_code() == ui::VKEY_RIGHT || - (event.key_code() == ui::VKEY_TAB && !event.IsShiftDown())) { - expand_arrow_view_->SetSelected(false); - // Move focus from the last element in contents view to the first element - // in search box view. - return false; - } - - if (event.key_code() == ui::VKEY_LEFT || event.key_code() == ui::VKEY_UP || - (event.key_code() == ui::VKEY_TAB && event.IsShiftDown())) { - expand_arrow_view_->SetSelected(false); - suggestions_container_->SetSelectedIndex( - suggestions_container_->num_results() - 1); - return true; - } - - return false; - } - if (custom_launcher_page_background_->selected()) { selected_index = suggestions_container_->num_results(); switch (event.key_code()) { @@ -352,13 +329,9 @@ dir = -forward_dir; break; case ui::VKEY_RIGHT: - // For non-fullscreen app list, don't go to the custom launcher page from - // the All apps tile. For fullscreen app list, allow this so that expand - // arrow is selected. - if (is_fullscreen_app_list_enabled_ || - selected_index != suggestions_container_->num_results() - 1) { + // Don't go to the custom launcher page from the All apps tile. + if (selected_index != suggestions_container_->num_results() - 1) dir = forward_dir; - } break; case ui::VKEY_UP: // Up selects the first tile if the custom launcher is selected. @@ -370,8 +343,7 @@ case ui::VKEY_DOWN: // Down selects the first tile if nothing is selected. dir = 1; - // If something is selected, for non-fullscreen app list, it selects the - // custom launcher page; for fullscreen app list, it selects expand arrow. + // If something is selected, select the custom launcher page. if (suggestions_container_->IsValidSelectionIndex(selected_index)) selected_index = suggestions_container_->num_results() - 1; break; @@ -386,12 +358,6 @@ return false; if (selected_index == -1) { - if (expand_arrow_view_ && !expand_arrow_view_->selected() && dir == -1) { - // Move focus from the first element in search box view to the last - // element in contents view. - expand_arrow_view_->SetSelected(true); - return true; - } custom_launcher_page_background_->SetSelected(false); suggestions_container_->SetSelectedIndex( dir == -1 ? suggestions_container_->num_results() - 1 : 0); @@ -405,13 +371,6 @@ return true; } - if (expand_arrow_view_ && - selection_index == suggestions_container_->num_results()) { - expand_arrow_view_->SetSelected(true); - suggestions_container_->ClearSelectedIndex(); - return true; - } - if (selection_index == suggestions_container_->num_results() && app_list_main_view_->ShouldShowCustomLauncherPage()) { custom_launcher_page_background_->SetSelected(true); @@ -511,4 +470,120 @@ view_item->layer()->SetOpacity(is_end_gesture_ ? 1.0f : opacity); } +// static +bool StartPageView::HandleKeyPressedFullscreen(const ui::KeyEvent& event) { + DCHECK(is_fullscreen_app_list_enabled_); + DCHECK(!!expand_arrow_view_); + + const int forward_dir = base::i18n::IsRTL() ? -1 : 1; + const int selected_index = suggestions_container_->selected_index(); + + if (expand_arrow_view_->selected()) { + if (expand_arrow_view_->OnKeyPressed(event)) { + expand_arrow_view_->SetSelected(false); + return true; + } + + if (event.key_code() == ui::VKEY_RIGHT || + event.key_code() == ui::VKEY_DOWN || + (event.key_code() == ui::VKEY_TAB && !event.IsShiftDown())) { + expand_arrow_view_->SetSelected(false); + // Move focus from expand arrow to search box. + return false; + } + + if (event.key_code() == ui::VKEY_LEFT || + (event.key_code() == ui::VKEY_TAB && event.IsShiftDown())) { + expand_arrow_view_->SetSelected(false); + if (suggestions_container_->num_results() == 0) + return false; + suggestions_container_->SetSelectedIndex( + suggestions_container_->num_results() - 1); + return true; + } + + if (event.key_code() == ui::VKEY_UP) { + expand_arrow_view_->SetSelected(false); + if (suggestions_container_->num_results() == 0) + return false; + // Move focus to the suggestion app in the middle. + suggestions_container_->SetSelectedIndex( + suggestions_container_->num_results() / 2); + return true; + } + + return false; + } + + if (selected_index >= 0 && + suggestions_container_->GetTileItemView(selected_index) + ->OnKeyPressed(event)) { + return true; + } + + if (event.key_code() == ui::VKEY_UP) { + if (selected_index == -1) { + // Move focus from search box to expand arrow. + expand_arrow_view_->SetSelected(true); + return true; + } + // Move focus from suggestion app to search box. + suggestions_container_->ClearSelectedIndex(); + return false; + } + + if (event.key_code() == ui::VKEY_DOWN) { + if (selected_index == -1 && suggestions_container_->num_results() > 0) { + // Move focus from search box to the suggestion app in the middle. + suggestions_container_->SetSelectedIndex( + suggestions_container_->num_results() / 2); + return true; + } + // Move focus from suggestion app to expand arrow. + suggestions_container_->ClearSelectedIndex(); + expand_arrow_view_->SetSelected(true); + return true; + } + + int dir = 0; + switch (event.key_code()) { + case ui::VKEY_LEFT: + dir = -forward_dir; + break; + case ui::VKEY_RIGHT: + dir = forward_dir; + break; + case ui::VKEY_TAB: + dir = event.IsShiftDown() ? -1 : 1; + break; + default: + return false; + } + + if (selected_index == -1) { + if (dir == -1) { + // Move focus from search box to expand arrow if moving backward. + expand_arrow_view_->SetSelected(true); + return true; + } + // Move focus from search box to the first suggestion app if moving forward. + suggestions_container_->SetSelectedIndex(0); + return true; + } + + int selection_index = selected_index + dir; + if (suggestions_container_->IsValidSelectionIndex(selection_index)) { + suggestions_container_->SetSelectedIndex(selection_index); + return true; + } + + suggestions_container_->ClearSelectedIndex(); + if (selection_index == suggestions_container_->num_results()) { + // Move focus from the last suggestion app to expand arrow. + expand_arrow_view_->SetSelected(true); + return true; + } + return false; +} + } // namespace app_list
diff --git a/ui/app_list/views/start_page_view.h b/ui/app_list/views/start_page_view.h index d1d4ddd..f9ca276b 100644 --- a/ui/app_list/views/start_page_view.h +++ b/ui/app_list/views/start_page_view.h
@@ -78,6 +78,9 @@ TileItemView* GetTileItemView(size_t index); + // Handles key events in fullscreen app list. + bool HandleKeyPressedFullscreen(const ui::KeyEvent& event); + AppListView* app_list_view_; // The parent view of ContentsView which is the parent of this view.
diff --git a/ui/login/account_picker/md_screen_account_picker.js b/ui/login/account_picker/md_screen_account_picker.js index 450535b..1ebf46f 100644 --- a/ui/login/account_picker/md_screen_account_picker.js +++ b/ui/login/account_picker/md_screen_account_picker.js
@@ -87,10 +87,9 @@ * wallpaper. * @param {string} maskColor Color for the gradient mask. * @param {string} scrollColor Color for the small pods container. - * @param {string} backgroundColor Color for the whole background. */ - setOverlayColors: function(maskColor, scrollColor, backgroundColor) { - $('pod-row').setOverlayColors(maskColor, scrollColor, backgroundColor); + setOverlayColors: function(maskColor, scrollColor) { + $('pod-row').setOverlayColors(maskColor, scrollColor); }, /**
diff --git a/ui/login/account_picker/md_user_pod_row.js b/ui/login/account_picker/md_user_pod_row.js index 218466d..4e94f28 100644 --- a/ui/login/account_picker/md_user_pod_row.js +++ b/ui/login/account_picker/md_user_pod_row.js
@@ -4170,10 +4170,8 @@ * wallpaper. * @param {string} maskColor Color for the gradient mask. * @param {string} scrollColor Color for the small pods container. - * @param {string} backgroundColor Color for the whole background. */ - setOverlayColors: function(maskColor, scrollColor, backgroundColor) { - $('login-shield').style.backgroundColor = backgroundColor; + setOverlayColors: function(maskColor, scrollColor) { if (this.smallPodsContainer.classList.contains('scroll')) this.smallPodsContainer.style.backgroundColor = scrollColor; if (!this.topMask.hidden) {
diff --git a/ui/login/md_screen_container.css b/ui/login/md_screen_container.css index 49a02a0..ba4c1fe 100644 --- a/ui/login/md_screen_container.css +++ b/ui/login/md_screen_container.css
@@ -63,16 +63,6 @@ pointer-events: none; } -#login-shield { - background-color: rgba(0, 0, 0, 0.6); - display: block; - height: 100%; - left: 0; - position: absolute; - top: 0; - width: 100%; -} - #oobe[md-mode] #progress-dots { display: none; }
diff --git a/ui/login/screen_container.css b/ui/login/screen_container.css index 24021fa..4ee8855 100644 --- a/ui/login/screen_container.css +++ b/ui/login/screen_container.css
@@ -63,20 +63,6 @@ pointer-events: none; } -#oobe-shield { - display: none; -} - -#oobe-shield[md-mode] { - background-color: rgba(0, 0, 0, 0.6); - display: block; - height: 100%; - left: 0; - position: absolute; - top: 0; - width: 100%; -} - #oobe[md-mode] #progress-dots { display: none; }
diff --git a/ui/snapshot/screenshot_grabber.cc b/ui/snapshot/screenshot_grabber.cc index da79cb2..bd56394 100644 --- a/ui/snapshot/screenshot_grabber.cc +++ b/ui/snapshot/screenshot_grabber.cc
@@ -7,7 +7,6 @@ #include <stddef.h> #include <climits> -#include <string> #include "base/bind.h" #include "base/callback.h" @@ -18,6 +17,7 @@ #include "base/message_loop/message_loop.h" #include "base/single_thread_task_runner.h" #include "base/task_runner.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/sequenced_worker_pool.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" @@ -103,10 +103,10 @@ void ScreenshotGrabberDelegate::PrepareFileAndRunOnBlockingPool( const base::FilePath& path, - scoped_refptr<base::TaskRunner> blocking_task_runner, const FileCallback& callback_on_blocking_pool) { - blocking_task_runner->PostTask( + base::PostTaskWithTraits( FROM_HERE, + {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, base::Bind(EnsureLocalDirectoryExists, path, callback_on_blocking_pool)); } @@ -139,13 +139,8 @@ }; #endif -ScreenshotGrabber::ScreenshotGrabber( - ScreenshotGrabberDelegate* client, - scoped_refptr<base::TaskRunner> blocking_task_runner) - : client_(client), - blocking_task_runner_(blocking_task_runner), - factory_(this) { -} +ScreenshotGrabber::ScreenshotGrabber(ScreenshotGrabberDelegate* client) + : client_(client), factory_(this) {} ScreenshotGrabber::~ScreenshotGrabber() { } @@ -169,7 +164,7 @@ cursor_hider_ = ScopedCursorHider::Create(aura_window->GetRootWindow()); #endif ui::GrabWindowSnapshotAsyncPNG( - window, rect, blocking_task_runner_, + window, rect, base::Bind(&ScreenshotGrabber::GrabWindowSnapshotAsyncCallback, factory_.GetWeakPtr(), window_identifier, screenshot_path, is_partial)); @@ -230,7 +225,7 @@ ShowNotificationCallback notification_callback(base::Bind( &ScreenshotGrabber::NotifyScreenshotCompleted, factory_.GetWeakPtr())); client_->PrepareFileAndRunOnBlockingPool( - screenshot_path, blocking_task_runner_, + screenshot_path, base::Bind(&SaveScreenshot, base::ThreadTaskRunnerHandle::Get(), notification_callback, screenshot_path, png_data)); }
diff --git a/ui/snapshot/screenshot_grabber.h b/ui/snapshot/screenshot_grabber.h index 7a0a947..8cf7723 100644 --- a/ui/snapshot/screenshot_grabber.h +++ b/ui/snapshot/screenshot_grabber.h
@@ -6,6 +6,7 @@ #define UI_SNAPSHOT_SCREENSHOT_GRABBER_H_ #include <memory> +#include <string> #include "base/callback.h" #include "base/compiler_specific.h" @@ -20,10 +21,6 @@ #include "ui/snapshot/screenshot_grabber_observer.h" #include "ui/snapshot/snapshot_export.h" -namespace base { -class TaskRunner; -} - namespace ui { // TODO(flackr): Componentize google drive so that we don't need the @@ -50,14 +47,12 @@ // the remote file and call the callback with the local path. virtual void PrepareFileAndRunOnBlockingPool( const base::FilePath& path, - scoped_refptr<base::TaskRunner> blocking_task_runner, const FileCallback& callback_on_blocking_pool); }; class SNAPSHOT_EXPORT ScreenshotGrabber { public: - ScreenshotGrabber(ScreenshotGrabberDelegate* client, - scoped_refptr<base::TaskRunner> blocking_task_runner); + explicit ScreenshotGrabber(ScreenshotGrabberDelegate* client); ~ScreenshotGrabber(); // Takes a screenshot of |rect| in |window| in that window's coordinate space @@ -92,9 +87,6 @@ // The timestamp when the screenshot task was issued last time. base::TimeTicks last_screenshot_timestamp_; - // Task runner for blocking tasks. - scoped_refptr<base::TaskRunner> blocking_task_runner_; - #if defined(USE_AURA) // The object to hide cursor when taking screenshot. std::unique_ptr<ScopedCursorHider> cursor_hider_;
diff --git a/ui/snapshot/snapshot.cc b/ui/snapshot/snapshot.cc index 6e5188c2..cc57fa9 100644 --- a/ui/snapshot/snapshot.cc +++ b/ui/snapshot/snapshot.cc
@@ -6,7 +6,7 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/task_runner_util.h" +#include "base/task_scheduler/post_task.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/image/image.h" @@ -22,7 +22,7 @@ std::vector<uint8_t> result; DCHECK(!image.AsImageSkia().GetRepresentation(1.0f).is_null()); gfx::PNGCodec::FastEncodeBGRASkBitmap(image.AsBitmap(), true, &result); - return new base::RefCountedBytes(result); + return base::RefCountedBytes::TakeVector(&result); } scoped_refptr<base::RefCountedMemory> EncodeImageAsJPEG( @@ -30,17 +30,17 @@ std::vector<uint8_t> result; DCHECK(!image.AsImageSkia().GetRepresentation(1.0f).is_null()); gfx::JPEG1xEncodedDataFromImage(image, 100, &result); - return new base::RefCountedBytes(result); + return base::RefCountedBytes::TakeVector(&result); } void EncodeImageAndScheduleCallback( scoped_refptr<base::RefCountedMemory> (*encode_func)(const gfx::Image&), - scoped_refptr<base::TaskRunner> background_task_runner, const base::Callback<void(scoped_refptr<base::RefCountedMemory> data)>& callback, const gfx::Image& image) { - base::PostTaskAndReplyWithResult(background_task_runner.get(), FROM_HERE, - base::Bind(encode_func, image), callback); + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, + base::Bind(encode_func, image), callback); } } // namespace @@ -48,23 +48,19 @@ void GrabWindowSnapshotAsyncPNG( gfx::NativeWindow window, const gfx::Rect& source_rect, - scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncPNGCallback& callback) { GrabWindowSnapshotAsync( window, source_rect, - base::Bind(EncodeImageAndScheduleCallback, &EncodeImageAsPNG, - std::move(background_task_runner), callback)); + base::Bind(EncodeImageAndScheduleCallback, &EncodeImageAsPNG, callback)); } void GrabWindowSnapshotAsyncJPEG( gfx::NativeWindow window, const gfx::Rect& source_rect, - scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncJPEGCallback& callback) { GrabWindowSnapshotAsync( window, source_rect, - base::Bind(EncodeImageAndScheduleCallback, &EncodeImageAsJPEG, - std::move(background_task_runner), callback)); + base::Bind(EncodeImageAndScheduleCallback, &EncodeImageAsJPEG, callback)); } } // namespace ui
diff --git a/ui/snapshot/snapshot.h b/ui/snapshot/snapshot.h index 31b9755a..f5b5fa4 100644 --- a/ui/snapshot/snapshot.h +++ b/ui/snapshot/snapshot.h
@@ -13,10 +13,6 @@ #include "ui/gfx/native_widget_types.h" #include "ui/snapshot/snapshot_export.h" -namespace base { -class TaskRunner; -} - namespace gfx { class Rect; class Image; @@ -48,7 +44,6 @@ gfx::NativeWindow window, const gfx::Rect& source_rect, const gfx::Size& target_size, - scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncCallback& callback); SNAPSHOT_EXPORT void GrabWindowSnapshotAsync( @@ -66,7 +61,6 @@ SNAPSHOT_EXPORT void GrabWindowSnapshotAsyncPNG( gfx::NativeWindow window, const gfx::Rect& source_rect, - scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncPNGCallback& callback); using GrabWindowSnapshotAsyncJPEGCallback = @@ -74,7 +68,6 @@ SNAPSHOT_EXPORT void GrabWindowSnapshotAsyncJPEG( gfx::NativeWindow window, const gfx::Rect& source_rect, - scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncJPEGCallback& callback); } // namespace ui
diff --git a/ui/snapshot/snapshot_android.cc b/ui/snapshot/snapshot_android.cc index 2011398..c209fa5 100644 --- a/ui/snapshot/snapshot_android.cc +++ b/ui/snapshot/snapshot_android.cc
@@ -8,7 +8,6 @@ #include <utility> #include "base/bind.h" -#include "base/task_runner.h" #include "components/viz/common/quads/copy_output_request.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/android/view_android.h" @@ -51,12 +50,10 @@ gfx::NativeWindow window, const gfx::Rect& source_rect, const gfx::Size& target_size, - scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncCallback& callback) { - MakeAsyncCopyRequest( - window, source_rect, - base::BindOnce(&SnapshotAsync::ScaleCopyOutputResult, callback, - target_size, background_task_runner)); + MakeAsyncCopyRequest(window, source_rect, + base::BindOnce(&SnapshotAsync::ScaleCopyOutputResult, + callback, target_size)); } void GrabWindowSnapshotAsync(gfx::NativeWindow window,
diff --git a/ui/snapshot/snapshot_async.cc b/ui/snapshot/snapshot_async.cc index e05553c..1eedc3c 100644 --- a/ui/snapshot/snapshot_async.cc +++ b/ui/snapshot/snapshot_async.cc
@@ -5,9 +5,8 @@ #include "ui/snapshot/snapshot_async.h" #include "base/location.h" -#include "base/memory/ref_counted.h" #include "base/numerics/safe_conversions.h" -#include "base/task_runner_util.h" +#include "base/task_scheduler/post_task.h" #include "skia/ext/image_operations.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/image/image.h" @@ -37,7 +36,6 @@ void SnapshotAsync::ScaleCopyOutputResult( const GrabWindowSnapshotAsyncCallback& callback, const gfx::Size& target_size, - scoped_refptr<base::TaskRunner> background_task_runner, std::unique_ptr<viz::CopyOutputResult> result) { if (result->IsEmpty()) { callback.Run(gfx::Image()); @@ -48,9 +46,8 @@ // from GPU. Image scaling is implemented in content::GlHelper, but it's can't // be used here because it's not in content/public. Move the scaling code // somewhere so that it can be reused here. - base::PostTaskAndReplyWithResult( - background_task_runner.get(), - FROM_HERE, + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, base::Bind(ScaleBitmap, *result->TakeBitmap(), target_size), base::Bind(&OnFrameScalingFinished, callback)); }
diff --git a/ui/snapshot/snapshot_async.h b/ui/snapshot/snapshot_async.h index 68b2bff..4c66cf0 100644 --- a/ui/snapshot/snapshot_async.h +++ b/ui/snapshot/snapshot_async.h
@@ -11,10 +11,6 @@ #include "components/viz/common/quads/copy_output_result.h" #include "ui/snapshot/snapshot.h" -namespace base { -class TaskRunner; -} - namespace gfx { class Size; } @@ -28,7 +24,6 @@ static void ScaleCopyOutputResult( const GrabWindowSnapshotAsyncCallback& callback, const gfx::Size& target_size, - scoped_refptr<base::TaskRunner> background_task_runner, std::unique_ptr<viz::CopyOutputResult> result); static void RunCallbackWithCopyOutputResult(
diff --git a/ui/snapshot/snapshot_aura.cc b/ui/snapshot/snapshot_aura.cc index 845f03e..40b59a11 100644 --- a/ui/snapshot/snapshot_aura.cc +++ b/ui/snapshot/snapshot_aura.cc
@@ -4,6 +4,7 @@ #include "ui/snapshot/snapshot_aura.h" +#include <memory> #include <utility> #include "base/bind.h" @@ -80,12 +81,11 @@ aura::Window* window, const gfx::Rect& source_rect, const gfx::Size& target_size, - scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncCallback& callback) { MakeInitialAsyncCopyRequest( window, source_rect, base::BindOnce(&SnapshotAsync::ScaleCopyOutputResult, callback, - target_size, background_task_runner)); + target_size)); } void GrabWindowSnapshotAsyncAura( @@ -116,10 +116,9 @@ gfx::NativeWindow window, const gfx::Rect& source_rect, const gfx::Size& target_size, - scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncCallback& callback) { GrabWindowSnapshotAndScaleAsyncAura(window, source_rect, target_size, - background_task_runner, callback); + callback); } void GrabWindowSnapshotAsync(gfx::NativeWindow window,
diff --git a/ui/snapshot/snapshot_aura.h b/ui/snapshot/snapshot_aura.h index 2c5429ce..7f69317 100644 --- a/ui/snapshot/snapshot_aura.h +++ b/ui/snapshot/snapshot_aura.h
@@ -19,7 +19,6 @@ aura::Window* window, const gfx::Rect& source_rect, const gfx::Size& target_size, - scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncCallback& callback); SNAPSHOT_EXPORT void GrabWindowSnapshotAsyncAura(
diff --git a/ui/snapshot/snapshot_ios.mm b/ui/snapshot/snapshot_ios.mm index d239b71..b0c57e8 100644 --- a/ui/snapshot/snapshot_ios.mm +++ b/ui/snapshot/snapshot_ios.mm
@@ -28,7 +28,6 @@ gfx::NativeWindow window, const gfx::Rect& snapshot_bounds, const gfx::Size& target_size, - scoped_refptr<base::TaskRunner> background_task_runner, GrabWindowSnapshotAsyncCallback callback) { callback.Run(gfx::Image()); }
diff --git a/ui/snapshot/snapshot_mac.mm b/ui/snapshot/snapshot_mac.mm index 40cfaaf..fab9c68 100644 --- a/ui/snapshot/snapshot_mac.mm +++ b/ui/snapshot/snapshot_mac.mm
@@ -10,7 +10,6 @@ #include "base/logging.h" #include "base/mac/scoped_cftyperef.h" #include "base/mac/sdk_forward_declarations.h" -#include "base/task_runner.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/image/image.h" @@ -69,7 +68,6 @@ gfx::NativeWindow window, const gfx::Rect& snapshot_bounds, const gfx::Size& target_size, - scoped_refptr<base::TaskRunner> background_task_runner, GrabWindowSnapshotAsyncCallback callback) { callback.Run(gfx::Image()); }
diff --git a/ui/snapshot/snapshot_win.cc b/ui/snapshot/snapshot_win.cc index cd0d8f1..17f4278f 100644 --- a/ui/snapshot/snapshot_win.cc +++ b/ui/snapshot/snapshot_win.cc
@@ -4,8 +4,9 @@ #include "ui/snapshot/snapshot_win.h" +#include <memory> + #include "base/callback.h" -#include "base/task_runner.h" #include "base/win/windows_version.h" #include "skia/ext/platform_canvas.h" #include "skia/ext/skia_utils_win.h" @@ -149,11 +150,10 @@ gfx::NativeWindow window, const gfx::Rect& source_rect, const gfx::Size& target_size, - scoped_refptr<base::TaskRunner> background_task_runner, const GrabWindowSnapshotAsyncCallback& callback) { if (UseAuraSnapshot()) { GrabWindowSnapshotAndScaleAsyncAura(window, source_rect, target_size, - background_task_runner, callback); + callback); return; } NOTIMPLEMENTED();