diff --git a/DEPS b/DEPS index b48a753c..ecf8e66 100644 --- a/DEPS +++ b/DEPS
@@ -59,7 +59,7 @@ # 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': '206bda5b79311da9a6ea0ee112302bf8115c41c5', + 'skia_revision': 'd29e0da3523e390eeb77b5a823d7ff86569ac1d3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -83,7 +83,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': 'a85e5ca5f2dfadcf9f3812a8ef039d1f206833a4', + 'pdfium_revision': '1bc5e494b675aeb5e73cae1d0d3cfad341a05a60', # 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. @@ -127,7 +127,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. - 'libprotobuf-mutator': '52af4b0f6f55f9d8836acb605e902db49eb8e6b4', + 'libprotobuf-mutator': '3fc43a01d721ef1bacfefed170bc22abf1b8b051', } # Only these hosts are allowed for dependencies in this DEPS file. @@ -440,7 +440,7 @@ }, 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + '401e6d48bfd3cbf74a41da724d05c989e207662b', + Var('chromium_git') + '/webm/libvpx.git' + '@' + '3ba9a2c8b2341430b001ed531f1eedf7c9b0384f', 'src/third_party/libwebm/source': Var('chromium_git') + '/webm/libwebm.git' + '@' + '4956b2dec65352af32dc71bab553acb631c64177', @@ -605,7 +605,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '34842fa3c36988840c89f5bc6a68503175acf7d9', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'c4a14324e29cd1210cfa5d0c061e7a1f10dacf00', # commit position 20528 + Var('webrtc_git') + '/src.git' + '@' + '6063e98dcb5044eb010bc69cc307b26925dd033b', # commit position 20528 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py index 9e9c4217..a18d9234 100755 --- a/PRESUBMIT_test.py +++ b/PRESUBMIT_test.py
@@ -504,7 +504,6 @@ 'android_clang_dbg_recipe', 'android_compile_dbg', 'android_compile_mips_dbg', - 'android_compile_rel', 'android_compile_x64_dbg', 'android_compile_x86_dbg', 'android_coverage',
diff --git a/WATCHLISTS b/WATCHLISTS index ff51440..32b755b 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -980,7 +980,8 @@ 'filepath': 'ipc/ipc', }, 'libvpx': { - 'filepath': 'third_party/libvpx' + 'filepath': 'third_party/libaom/|'\ + 'third_party/libvpx/', }, 'libwebp': { 'filepath': 'third_party/libwebp'
diff --git a/ash/mus/window_manager.cc b/ash/mus/window_manager.cc index 2eabaa1..e72b1a8 100644 --- a/ash/mus/window_manager.cc +++ b/ash/mus/window_manager.cc
@@ -29,6 +29,7 @@ #include "ash/public/cpp/window_state_type.h" #include "ash/public/interfaces/window_actions.mojom.h" #include "ash/public/interfaces/window_pin_type.mojom.h" +#include "ash/public/interfaces/window_properties.mojom.h" #include "ash/public/interfaces/window_state_type.mojom.h" #include "ash/root_window_controller.h" #include "ash/root_window_settings.h" @@ -106,6 +107,10 @@ property_converter_->RegisterPrimitiveProperty( kWindowPinTypeKey, ash::mojom::kWindowPinType_Property, base::Bind(&ash::IsValidWindowPinType)); + property_converter_->RegisterPrimitiveProperty( + kWindowPositionManagedTypeKey, + ash::mojom::kWindowPositionManaged_Property, + aura::PropertyConverter::CreateAcceptAnyValueCallback()); property_converter_->RegisterStringProperty( kShelfIDKey, ui::mojom::WindowManager::kShelfID_Property); }
diff --git a/ash/public/cpp/window_properties.cc b/ash/public/cpp/window_properties.cc index de6a0d9..f780615 100644 --- a/ash/public/cpp/window_properties.cc +++ b/ash/public/cpp/window_properties.cc
@@ -19,11 +19,12 @@ DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kShelfIDKey, nullptr); DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kShelfItemTypeKey, TYPE_UNDEFINED); DEFINE_UI_CLASS_PROPERTY_KEY(bool, kShowInOverviewKey, true); -DEFINE_UI_CLASS_PROPERTY_KEY(mojom::WindowStateType, - kWindowStateTypeKey, - mojom::WindowStateType::DEFAULT); DEFINE_UI_CLASS_PROPERTY_KEY(mojom::WindowPinType, kWindowPinTypeKey, mojom::WindowPinType::NONE); +DEFINE_UI_CLASS_PROPERTY_KEY(bool, kWindowPositionManagedTypeKey, false); +DEFINE_UI_CLASS_PROPERTY_KEY(mojom::WindowStateType, + kWindowStateTypeKey, + mojom::WindowStateType::DEFAULT); } // namespace ash
diff --git a/ash/public/cpp/window_properties.h b/ash/public/cpp/window_properties.h index 89eb4f5..8e4ea5f 100644 --- a/ash/public/cpp/window_properties.h +++ b/ash/public/cpp/window_properties.h
@@ -44,10 +44,6 @@ ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const kShowInOverviewKey; -// A property key to indicate ash's extended window state. -ASH_PUBLIC_EXPORT extern const aura::WindowProperty< - mojom::WindowStateType>* const kWindowStateTypeKey; - // A property key to store ash::WindowPinType for a window. // When setting this property to PINNED or TRUSTED_PINNED, the window manager // will try to fullscreen the window and pin it on the top of the screen. If the @@ -56,6 +52,16 @@ ASH_PUBLIC_EXPORT extern const aura::WindowProperty<mojom::WindowPinType>* const kWindowPinTypeKey; +// A property key to indicate whether ash should perform auto management of +// window positions; when you open a second browser, ash will move the two to +// minimize overlap. +ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const + kWindowPositionManagedTypeKey; + +// A property key to indicate ash's extended window state. +ASH_PUBLIC_EXPORT extern const aura::WindowProperty< + mojom::WindowStateType>* const kWindowStateTypeKey; + // Alphabetical sort. } // namespace ash
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn index b1aaaa13..3aa2427 100644 --- a/ash/public/interfaces/BUILD.gn +++ b/ash/public/interfaces/BUILD.gn
@@ -42,6 +42,7 @@ "wallpaper.mojom", "window_actions.mojom", "window_pin_type.mojom", + "window_properties.mojom", "window_state_type.mojom", "window_style.mojom", ]
diff --git a/ash/public/interfaces/window_properties.mojom b/ash/public/interfaces/window_properties.mojom new file mode 100644 index 0000000..8d2ee1fa --- /dev/null +++ b/ash/public/interfaces/window_properties.mojom
@@ -0,0 +1,11 @@ +// 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 ash.mojom; + +// This is put on windows to indicate that ash should perform auto management of +// window positions; when you open a second browser, ash will move the two to +// minimize overlap. +const string kWindowPositionManaged_Property = + "ash:window-position-managed";
diff --git a/ash/shelf/voice_interaction_overlay.cc b/ash/shelf/voice_interaction_overlay.cc index b5136d5..93f2f94 100644 --- a/ash/shelf/voice_interaction_overlay.cc +++ b/ash/shelf/voice_interaction_overlay.cc
@@ -114,7 +114,8 @@ } // namespace -class VoiceInteractionIcon : public ui::Layer { +class VoiceInteractionIcon : public ui::Layer, + public ui::CompositorAnimationObserver { public: VoiceInteractionIcon() : Layer(ui::LAYER_NOT_DRAWN) { set_name("VoiceInteractionOverlay:ICON_LAYER"); @@ -126,14 +127,32 @@ } void StartAnimation() { - animation_timer_.Start(FROM_HERE, - base::TimeDelta::FromMilliseconds( - base::TimeTicks::kMillisecondsPerSecond / - gfx::LinearAnimation::kDefaultFrameRate), - this, &VoiceInteractionIcon::AnimationProgressed); + if (!GetCompositor()->HasAnimationObserver(this)) + GetCompositor()->AddAnimationObserver(this); } - void StopAnimation() { animation_timer_.Stop(); } + void StopAnimation() { + if (GetCompositor()->HasAnimationObserver(this)) + GetCompositor()->RemoveAnimationObserver(this); + } + + // ui::CompositorAnimationObserver + void OnCompositingShuttingDown(ui::Compositor* compositor) override {} + void OnAnimationStep(base::TimeTicks timestamp) override { + uint64_t elapsed = (timestamp - base::TimeTicks()).InMilliseconds(); + for (int i = 0; i < DOT_COUNT; ++i) { + float normalizedTime = + ((elapsed - kMoleculeAnimationOffset * kMoleculeOrder[i]) % + kMoleculeAnimationDurationMs) / + static_cast<float>(kMoleculeAnimationDurationMs); + + gfx::Transform transform; + transform.Translate(0, + kMoleculeAmplitude * sin(normalizedTime * 2 * M_PI)); + + dot_layers_[i]->SetTransform(transform); + } + } private: enum Dot { @@ -162,25 +181,6 @@ return "UNKNOWN"; } - void AnimationProgressed() { - gfx::Transform transform; - - uint64_t now = - (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds(); - for (int i = 0; i < DOT_COUNT; ++i) { - float normalizedTime = - ((now - kMoleculeAnimationOffset * kMoleculeOrder[i]) % - kMoleculeAnimationDurationMs) / - static_cast<float>(kMoleculeAnimationDurationMs); - - transform.MakeIdentity(); - transform.Translate(0, - kMoleculeAmplitude * sin(normalizedTime * 2 * M_PI)); - - dot_layers_[i]->SetTransform(transform); - } - } - /** * Convenience method to place dots to Molecule shape used by Molecule * animations. @@ -209,8 +209,6 @@ std::unique_ptr<ui::Layer> dot_layers_[DOT_COUNT]; std::unique_ptr<views::CircleLayerDelegate> dot_layer_delegates_[DOT_COUNT]; - base::RepeatingTimer animation_timer_; - DISALLOW_COPY_AND_ASSIGN(VoiceInteractionIcon); };
diff --git a/ash/shell/toplevel_window.cc b/ash/shell/toplevel_window.cc index bb373e7..2a8970d 100644 --- a/ash/shell/toplevel_window.cc +++ b/ash/shell/toplevel_window.cc
@@ -38,7 +38,7 @@ new ToplevelWindow(params), Shell::GetPrimaryRootWindow()); widget->GetNativeView()->SetName("Examples:ToplevelWindow"); wm::WindowState* window_state = wm::GetWindowState(widget->GetNativeView()); - window_state->set_window_position_managed(true); + window_state->SetWindowPositionManaged(true); widget->Show(); return widget; }
diff --git a/ash/system/palette/palette_tray.cc b/ash/system/palette/palette_tray.cc index 4c472e4b..adea79f3 100644 --- a/ash/system/palette/palette_tray.cc +++ b/ash/system/palette/palette_tray.cc
@@ -183,10 +183,10 @@ void PaletteTray::RegisterProfilePrefs(PrefRegistrySimple* registry) { registry->RegisterBooleanPref( prefs::kEnableStylusTools, true, - user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC); registry->RegisterBooleanPref( prefs::kLaunchPaletteOnEjectEvent, true, - user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC); } bool PaletteTray::ContainsPointInScreen(const gfx::Point& point) {
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc index 8a9d929..aa70c0c 100644 --- a/ash/wm/splitview/split_view_controller.cc +++ b/ash/wm/splitview/split_view_controller.cc
@@ -31,20 +31,14 @@ namespace { -// Five fixed position ratios of the divider. -constexpr float kFixedPositionRatios[] = {0.0f, 0.33f, 0.5f, 0.67f, 1.0f}; +// Three fixed position ratios of the divider, which means the divider can +// always be moved to these three positions. +constexpr float kFixedPositionRatios[] = {0.f, 0.5f, 1.0f}; -float FindClosestFixedPositionRatio(float distance, float length) { - float current_ratio = distance / length; - float closest_ratio = 0.f; - for (float ratio : kFixedPositionRatios) { - if (std::abs(current_ratio - ratio) < - std::abs(current_ratio - closest_ratio)) { - closest_ratio = ratio; - } - } - return closest_ratio; -} +// Two optional position ratios of the divider. Whether the divider can be moved +// to these two positions depends on the minimum size of the snapped windows. +constexpr float kOneThirdPositionRatio = 0.33f; +constexpr float kTwoThirdPositionRatio = 0.67f; gfx::Point GetBoundedPosition(const gfx::Point& location_in_screen, const gfx::Rect& bounds_in_screen) { @@ -608,41 +602,53 @@ SplitViewController::SnapPosition SplitViewController::GetBlackScrimPosition( const gfx::Point& location_in_screen) { - SnapPosition position = SplitViewController::NONE; const gfx::Rect work_area_bounds = GetDisplayWorkAreaBoundsInScreen(GetDefaultSnappedWindow()); if (!work_area_bounds.Contains(location_in_screen)) - return position; + return NONE; - switch (screen_orientation_) { - case blink::kWebScreenOrientationLockLandscapePrimary: - case blink::kWebScreenOrientationLockLandscapeSecondary: - if (location_in_screen.x() < - work_area_bounds.x() + - work_area_bounds.width() * kFixedPositionRatios[1]) { - position = IsCurrentScreenOrientationPrimary() ? LEFT : RIGHT; - } else if (location_in_screen.x() > - work_area_bounds.x() + - work_area_bounds.width() * kFixedPositionRatios[3]) { - position = IsCurrentScreenOrientationPrimary() ? RIGHT : LEFT; - } - break; - case blink::kWebScreenOrientationLockPortraitPrimary: - case blink::kWebScreenOrientationLockPortraitSecondary: - if (location_in_screen.y() > - work_area_bounds.y() + - work_area_bounds.height() * kFixedPositionRatios[3]) { - position = IsCurrentScreenOrientationPrimary() ? LEFT : RIGHT; - } else if (location_in_screen.y() < - work_area_bounds.y() + - work_area_bounds.height() * kFixedPositionRatios[1]) { - position = IsCurrentScreenOrientationPrimary() ? RIGHT : LEFT; - } - break; - default: - break; + gfx::Size left_window_min_size, right_window_min_size; + if (left_window_ && left_window_->delegate()) + left_window_min_size = left_window_->delegate()->GetMinimumSize(); + if (right_window_ && right_window_->delegate()) + right_window_min_size = right_window_->delegate()->GetMinimumSize(); + + bool is_primary = IsCurrentScreenOrientationPrimary(); + int long_length = GetDividerEndPosition(); + // The distance from the current resizing position to the left or right side + // of the screen. Note: left or right side here means the side of the + // |left_window_| or |right_window_|. + int left_window_distance = 0, right_window_distance = 0; + int min_left_length = 0, min_right_length = 0; + + if (IsCurrentScreenOrientationLandscape()) { + int left_distance = location_in_screen.x() - work_area_bounds.x(); + int right_distance = work_area_bounds.right() - location_in_screen.x(); + left_window_distance = is_primary ? left_distance : right_distance; + right_window_distance = is_primary ? right_distance : left_distance; + + min_left_length = left_window_min_size.width(); + min_right_length = right_window_min_size.width(); + } else { + int top_distance = location_in_screen.y() - work_area_bounds.y(); + int bottom_distance = work_area_bounds.bottom() - location_in_screen.y(); + left_window_distance = is_primary ? bottom_distance : top_distance; + right_window_distance = is_primary ? top_distance : bottom_distance; + + min_left_length = left_window_min_size.height(); + min_right_length = right_window_min_size.height(); } - return position; + + if (left_window_distance < long_length * kOneThirdPositionRatio || + left_window_distance < min_left_length) { + return LEFT; + } + if (right_window_distance < long_length * kOneThirdPositionRatio || + right_window_distance < min_right_length) { + return RIGHT; + } + + return NONE; } void SplitViewController::UpdateDividerPosition( @@ -699,11 +705,25 @@ // extract the center from |divider_position_|. The result will also be the // center of the divider, so extract the origin, unless the result is on of // the endpoints. - float ratio = FindClosestFixedPositionRatio( - divider_position_ + std::floor(divider_thickness / 2.f), - GetDividerEndPosition()); - divider_position_ = std::floor(GetDividerEndPosition() * ratio); - if (ratio > 0.f && ratio < 1.f) + float divider_distance = + divider_position_ + std::floor(divider_thickness / 2.f); + + int work_area_long_length = GetDividerEndPosition(); + float current_ratio = divider_distance / work_area_long_length; + float closest_ratio = 0.f; + std::vector<float> position_ratios( + kFixedPositionRatios, + kFixedPositionRatios + sizeof(kFixedPositionRatios) / sizeof(float)); + GetDividerOptionalPositionRatios(position_ratios); + for (float ratio : position_ratios) { + if (std::abs(current_ratio - ratio) < + std::abs(current_ratio - closest_ratio)) { + closest_ratio = ratio; + } + } + + divider_position_ = std::floor(work_area_long_length * closest_ratio); + if (closest_ratio > 0.f && closest_ratio < 1.f) divider_position_ -= std::floor(divider_thickness / 2.f); } @@ -790,4 +810,34 @@ TransposeRect(left_or_top_rect); } +void SplitViewController::GetDividerOptionalPositionRatios( + std::vector<float>& position_ratios) { + bool is_left_or_top = IsLeftWindowOnTopOrLeftOfScreen(screen_orientation_); + aura::Window* left_or_top_window = + is_left_or_top ? left_window_ : right_window_; + aura::Window* right_or_bottom_window = + is_left_or_top ? right_window_ : left_window_; + bool is_landscape = IsCurrentScreenOrientationLandscape(); + + int long_length = GetDividerEndPosition(); + float min_size_left_ratio = 0.f, min_size_right_ratio = 0.f; + int min_left_size = 0, min_right_size = 0; + if (left_or_top_window && left_or_top_window->delegate()) { + gfx::Size min_size = left_or_top_window->delegate()->GetMinimumSize(); + min_left_size = is_landscape ? min_size.width() : min_size.height(); + } + if (right_or_bottom_window && right_or_bottom_window->delegate()) { + gfx::Size min_size = right_or_bottom_window->delegate()->GetMinimumSize(); + min_right_size = is_landscape ? min_size.width() : min_size.height(); + } + + min_size_left_ratio = static_cast<float>(min_left_size) / long_length; + min_size_right_ratio = static_cast<float>(min_right_size) / long_length; + if (min_size_left_ratio <= kOneThirdPositionRatio) + position_ratios.push_back(kOneThirdPositionRatio); + + if (min_size_right_ratio <= kOneThirdPositionRatio) + position_ratios.push_back(kTwoThirdPositionRatio); +} + } // namespace ash
diff --git a/ash/wm/splitview/split_view_controller.h b/ash/wm/splitview/split_view_controller.h index 33e9218..1a0e7e7 100644 --- a/ash/wm/splitview/split_view_controller.h +++ b/ash/wm/splitview/split_view_controller.h
@@ -215,6 +215,12 @@ void AdjustLeftOrTopSnappedWindowBoundsDuringResizing( gfx::Rect* left_or_top_rect); + // Gets the divider optional position ratios. The divider can always be + // moved to the positions in |kFixedPositionRatios|. Whether the divider can + // be moved to |kOneThirdPositionRatio| or |kTwoThirdPositionRatio| depends + // on the minimum size of current snapped windows. + void GetDividerOptionalPositionRatios(std::vector<float>& positionRatios); + // The current left/right snapped window. aura::Window* left_window_ = nullptr; aura::Window* right_window_ = nullptr;
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc index 2aa4db7..ba11276 100644 --- a/ash/wm/splitview/split_view_controller_unittest.cc +++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -84,6 +84,12 @@ return split_view_controller()->split_view_divider(); } + blink::WebScreenOrientationLockType screen_orientation() { + return split_view_controller()->screen_orientation(); + } + + int divider_position() { return split_view_controller()->divider_position(); } + private: class SplitViewTestWindowDelegate : public aura::test::TestWindowDelegate { public: @@ -959,4 +965,87 @@ EndSplitView(); } +// Tests that if a snapped window's minumum size is larger than one third but +// smaller than half of the work area's longer side. The divider should be +// snapped to a position that is larger than the window's minimum size. +TEST_F(SplitViewControllerTest, DividerPositionWithWindowMinimumSizeTest) { + const gfx::Rect bounds(0, 0, 200, 200); + std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); + aura::test::TestWindowDelegate* delegate1 = + static_cast<aura::test::TestWindowDelegate*>(window1->delegate()); + ui::test::EventGenerator& generator(GetEventGenerator()); + EXPECT_EQ(blink::kWebScreenOrientationLockLandscapePrimary, + screen_orientation()); + gfx::Rect workarea_bounds = + split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window1.get()); + + // Snap the divider to one third position when there is only left window with + // minimum size larger than one third of the display's width. The divider + // should be snapped to the middle position after dragging. + split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT); + delegate1->set_minimum_size( + gfx::Size(workarea_bounds.width() * 0.4f, workarea_bounds.height())); + gfx::Rect divider_bounds = + split_view_divider()->GetDividerBoundsInScreen(false); + generator.set_current_location(divider_bounds.CenterPoint()); + generator.DragMouseTo(gfx::Point(workarea_bounds.width() * 0.33f, 0)); + EXPECT_GT(divider_position(), 0.33f * workarea_bounds.width()); + EXPECT_LE(divider_position(), 0.5f * workarea_bounds.width()); + + // Snap the divider to two third position, it should be kept at there after + // dragging. + generator.set_current_location(divider_bounds.CenterPoint()); + generator.DragMouseTo(gfx::Point(workarea_bounds.width() * 0.67f, 0)); + EXPECT_GT(divider_position(), 0.5f * workarea_bounds.width()); + EXPECT_LE(divider_position(), 0.67f * workarea_bounds.width()); + EndSplitView(); + + // Snap the divider to two third position when there is only right window with + // minium size larger than one third of the display's width. The divider + // should be snapped to the middle position after dragging. + delegate1->set_minimum_size( + gfx::Size(workarea_bounds.width() * 0.4f, workarea_bounds.height())); + split_view_controller()->SnapWindow(window1.get(), + SplitViewController::RIGHT); + divider_bounds = split_view_divider()->GetDividerBoundsInScreen(false); + generator.set_current_location(divider_bounds.CenterPoint()); + generator.DragMouseTo(gfx::Point(workarea_bounds.width() * 0.67f, 0)); + EXPECT_GT(divider_position(), 0.33f * workarea_bounds.width()); + EXPECT_LE(divider_position(), 0.5f * workarea_bounds.width()); + + // Snap the divider to one third position, it should be kept at there after + // dragging. + generator.set_current_location(divider_bounds.CenterPoint()); + generator.DragMouseTo(gfx::Point(workarea_bounds.width() * 0.33f, 0)); + EXPECT_GT(divider_position(), 0); + EXPECT_LE(divider_position(), 0.33f * workarea_bounds.width()); + EndSplitView(); + + // Snap the divider to one third position when there are both left and right + // snapped windows with the same minimum size larger than one third of the + // display's width. The divider should be snapped to the middle position after + // dragging. + std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + aura::test::TestWindowDelegate* delegate2 = + static_cast<aura::test::TestWindowDelegate*>(window2->delegate()); + delegate2->set_minimum_size( + gfx::Size(workarea_bounds.width() * 0.4f, workarea_bounds.height())); + split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT); + split_view_controller()->SnapWindow(window2.get(), + SplitViewController::RIGHT); + divider_bounds = split_view_divider()->GetDividerBoundsInScreen(false); + generator.set_current_location(divider_bounds.CenterPoint()); + generator.DragMouseTo(gfx::Point(workarea_bounds.width() * 0.33f, 0)); + EXPECT_GT(divider_position(), 0.33f * workarea_bounds.width()); + EXPECT_LE(divider_position(), 0.5f * workarea_bounds.width()); + + // Snap the divider to two third position, it should be snapped to the middle + // position after dragging. + generator.set_current_location(divider_bounds.CenterPoint()); + generator.DragMouseTo(gfx::Point(workarea_bounds.width() * 0.67f, 0)); + EXPECT_GT(divider_position(), 0.33f * workarea_bounds.width()); + EXPECT_LE(divider_position(), 0.5f * workarea_bounds.width()); + EndSplitView(); +} + } // namespace ash
diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc index adaa9f6..e498df2 100644 --- a/ash/wm/toplevel_window_event_handler.cc +++ b/ash/wm/toplevel_window_event_handler.cc
@@ -89,8 +89,8 @@ // Disable window position auto management while dragging and restore it // aftrewards. wm::WindowState* window_state = wm::GetWindowState(source); - const bool window_position_managed = window_state->window_position_managed(); - window_state->set_window_position_managed(false); + const bool window_position_managed = window_state->GetWindowPositionManaged(); + window_state->SetWindowPositionManaged(false); aura::WindowTracker tracker({source}); run_loop.Run(); @@ -100,7 +100,7 @@ // Make sure the window hasn't been deleted. if (tracker.Contains(source)) - window_state->set_window_position_managed(window_position_managed); + window_state->SetWindowPositionManaged(window_position_managed); in_move_loop_ = false; return result == wm::WmToplevelWindowEventHandler::DragResult::SUCCESS
diff --git a/ash/wm/toplevel_window_event_handler_unittest.cc b/ash/wm/toplevel_window_event_handler_unittest.cc index 32b2537..c82f0a9 100644 --- a/ash/wm/toplevel_window_event_handler_unittest.cc +++ b/ash/wm/toplevel_window_event_handler_unittest.cc
@@ -112,7 +112,7 @@ wm::WindowState* window_state, aura::Window* window) { ASSERT_TRUE(window->HasCapture()); - ASSERT_FALSE(window_state->window_position_managed()); + ASSERT_FALSE(window_state->GetWindowPositionManaged()); generator->DragMouseBy(100, 100); generator->ReleaseLeftButton(); } @@ -129,7 +129,7 @@ // Explicitly enable window position auto management, and expect it to be // restored after drag completes. - window_state->set_window_position_managed(true); + window_state->SetWindowPositionManaged(true); generator.PressLeftButton(); ::wm::WindowMoveClient* move_client = ::wm::GetWindowMoveClient(w1->GetRootWindow()); @@ -141,7 +141,7 @@ move_client->RunMoveLoop(w1.get(), gfx::Vector2d(100, 100), ::wm::WINDOW_MOVE_SOURCE_MOUSE)); // Window position auto manage property should be restored to true. - EXPECT_TRUE(window_state->window_position_managed()); + EXPECT_TRUE(window_state->GetWindowPositionManaged()); // Position should have been offset by 100,100. EXPECT_EQ("100,100", w1->bounds().origin().ToString()); // Size should remain the same. @@ -149,7 +149,7 @@ // Explicitly disable window position auto management, and expect it to be // restored after drag completes. - window_state->set_window_position_managed(false); + window_state->SetWindowPositionManaged(false); generator.PressLeftButton(); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, @@ -159,7 +159,7 @@ move_client->RunMoveLoop(w1.get(), gfx::Vector2d(100, 100), ::wm::WINDOW_MOVE_SOURCE_MOUSE)); // Window position auto manage property should be restored to true. - EXPECT_FALSE(window_state->window_position_managed()); + EXPECT_FALSE(window_state->GetWindowPositionManaged()); // Position should have been offset by 100,100. EXPECT_EQ("200,200", w1->bounds().origin().ToString()); // Size should remain the same.
diff --git a/ash/wm/window_positioner.cc b/ash/wm/window_positioner.cc index 22160d2..0f89656 100644 --- a/ash/wm/window_positioner.cc +++ b/ash/wm/window_positioner.cc
@@ -55,7 +55,8 @@ if (disable_auto_positioning) return false; const wm::WindowState* window_state = wm::GetWindowState(window); - return !window_state->is_dragged() && window_state->window_position_managed(); + return !window_state->is_dragged() && + window_state->GetWindowPositionManaged(); } // Check if a given |window| can be managed. This includes that its @@ -66,7 +67,7 @@ if (disable_auto_positioning) return false; const wm::WindowState* window_state = wm::GetWindowState(window); - return window_state->window_position_managed() && + return window_state->GetWindowPositionManaged() && !window_state->IsMinimized() && !window_state->IsMaximized() && !window_state->IsFullscreen() && !window_state->IsPinned() && !window_state->bounds_changed_by_user(); @@ -196,7 +197,7 @@ if (window != exclude && window->type() == aura::client::WINDOW_TYPE_NORMAL && window->GetRootWindow() == root_window && window->TargetVisibility() && - wm::GetWindowState(window)->window_position_managed()) { + wm::GetWindowState(window)->GetWindowPositionManaged()) { if (found && found != window) { // no need to check !single_window because the function must have // been already returned in the "if (!single_window)" below.
diff --git a/ash/wm/window_positioner_unittest.cc b/ash/wm/window_positioner_unittest.cc index afb6fb61..cc80299 100644 --- a/ash/wm/window_positioner_unittest.cc +++ b/ash/wm/window_positioner_unittest.cc
@@ -192,7 +192,7 @@ views::Widget* widget1 = shell::ToplevelWindow::CreateToplevelWindow(params); wm::WindowState* managed_state = wm::GetWindowState(widget1->GetNativeWindow()); - EXPECT_TRUE(managed_state->window_position_managed()); + EXPECT_TRUE(managed_state->GetWindowPositionManaged()); EXPECT_EQ("300x300", widget1->GetWindowBoundsInScreen().size().ToString()); widget1->SetFullscreen(true); ASSERT_EQ("1400x800", widget1->GetWindowBoundsInScreen().size().ToString()); @@ -201,7 +201,7 @@ params.use_saved_placement = false; views::Widget* widget2 = shell::ToplevelWindow::CreateToplevelWindow(params); wm::WindowState* state_2 = wm::GetWindowState(widget2->GetNativeWindow()); - EXPECT_TRUE(state_2->window_position_managed()); + EXPECT_TRUE(state_2->GetWindowPositionManaged()); EXPECT_EQ("300x300", widget2->GetWindowBoundsInScreen().size().ToString()); // Restores to the original size.
diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc index 654d5188..b0b147a 100644 --- a/ash/wm/window_state.cc +++ b/ash/wm/window_state.cc
@@ -328,6 +328,14 @@ observer_list_.RemoveObserver(observer); } +bool WindowState::GetWindowPositionManaged() const { + return window_->GetProperty(kWindowPositionManagedTypeKey); +} + +void WindowState::SetWindowPositionManaged(bool managed) { + window_->SetProperty(kWindowPositionManagedTypeKey, managed); +} + void WindowState::set_bounds_changed_by_user(bool bounds_changed_by_user) { bounds_changed_by_user_ = bounds_changed_by_user; if (bounds_changed_by_user) @@ -353,7 +361,6 @@ WindowState::WindowState(aura::Window* window) : window_(window), - window_position_managed_(false), bounds_changed_by_user_(false), ignored_by_shelf_(false), can_consume_system_keys_(false),
diff --git a/ash/wm/window_state.h b/ash/wm/window_state.h index e14e995..6bf98b84 100644 --- a/ash/wm/window_state.h +++ b/ash/wm/window_state.h
@@ -226,7 +226,7 @@ // If the minimum visibility is true, ash will try to keep a // minimum amount of the window is always visible on the work area // when shown. - // TODO(oshima): Consolidate this and window_position_managed + // TODO(oshima): Consolidate this and GetWindowPositionManaged // into single parameter to control the window placement. bool minimum_visibility() const { return minimum_visibility_; } void set_minimum_visibility(bool minimum_visibility) { @@ -256,10 +256,8 @@ // Whether or not the window's position can be managed by the // auto management logic. - bool window_position_managed() const { return window_position_managed_; } - void set_window_position_managed(bool window_position_managed) { - window_position_managed_ = window_position_managed; - } + bool GetWindowPositionManaged() const; + void SetWindowPositionManaged(bool managed); // Whether or not the window's position or size was changed by a user. bool bounds_changed_by_user() const { return bounds_changed_by_user_; } @@ -384,7 +382,6 @@ aura::Window* window_; std::unique_ptr<WindowStateDelegate> delegate_; - bool window_position_managed_; bool bounds_changed_by_user_; bool ignored_by_shelf_; bool can_consume_system_keys_;
diff --git a/ash/wm/window_state_unittest.cc b/ash/wm/window_state_unittest.cc index dd1096e..07cd311 100644 --- a/ash/wm/window_state_unittest.cc +++ b/ash/wm/window_state_unittest.cc
@@ -253,7 +253,7 @@ TEST_F(WindowStateTest, AutoManaged) { std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0)); WindowState* window_state = GetWindowState(window.get()); - window_state->set_window_position_managed(true); + window_state->SetWindowPositionManaged(true); window->Hide(); window->SetBounds(gfx::Rect(100, 100, 100, 100)); window->Show(); @@ -271,7 +271,7 @@ window->GetBoundsInScreen().ToString()); // The window should still be auto managed despite being right maximized. - EXPECT_TRUE(window_state->window_position_managed()); + EXPECT_TRUE(window_state->GetWindowPositionManaged()); } // Test that the replacement of a State object works as expected.
diff --git a/ash/wm/workspace_controller_unittest.cc b/ash/wm/workspace_controller_unittest.cc index afd8cb4..67828d3 100644 --- a/ash/wm/workspace_controller_unittest.cc +++ b/ash/wm/workspace_controller_unittest.cc
@@ -101,7 +101,7 @@ aura::Window* window = CreateTestWindow(); window->SetBounds(bounds); wm::WindowState* window_state = wm::GetWindowState(window); - window_state->set_window_position_managed(true); + window_state->SetWindowPositionManaged(true); window->Show(); return window; } @@ -764,7 +764,7 @@ // Create an auto-positioned window. std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); gfx::Rect desktop_area = window1->parent()->bounds(); - wm::GetWindowState(window1.get())->set_window_position_managed(true); + wm::GetWindowState(window1.get())->SetWindowPositionManaged(true); // Hide and then show |window1| to trigger auto-positioning logic. window1->Hide(); window1->SetBounds(gfx::Rect(16, 32, 300, 300)); @@ -791,7 +791,7 @@ // Create and show a second window forcing the first window and its child to // move. std::unique_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); - wm::GetWindowState(window2.get())->set_window_position_managed(true); + wm::GetWindowState(window2.get())->SetWindowPositionManaged(true); // Hide and then show |window2| to trigger auto-positioning logic. window2->Hide(); window2->SetBounds(gfx::Rect(32, 48, 250, 250)); @@ -833,10 +833,10 @@ wm::WindowState* window1_state = wm::GetWindowState(window1.get()); // Test 2: Set up two managed windows and check their auto positioning. - window1_state->set_window_position_managed(true); + window1_state->SetWindowPositionManaged(true); std::unique_ptr<aura::Window> window3(CreateTestWindowInShellWithId(2)); - wm::GetWindowState(window3.get())->set_window_position_managed(true); + wm::GetWindowState(window3.get())->SetWindowPositionManaged(true); // To avoid any auto window manager changes due to SetBounds, the window // gets first hidden and then shown again. window3->Hide(); @@ -897,8 +897,8 @@ wm::WindowState* window1_state = wm::GetWindowState(window1.get()); wm::WindowState* window2_state = wm::GetWindowState(window2.get()); - window1_state->set_window_position_managed(true); - window2_state->set_window_position_managed(true); + window1_state->SetWindowPositionManaged(true); + window2_state->SetWindowPositionManaged(true); EXPECT_FALSE(window1_state->bounds_changed_by_user()); EXPECT_FALSE(window2_state->bounds_changed_by_user()); @@ -943,9 +943,9 @@ window1->Hide(); window2->Hide(); window3->Hide(); - wm::GetWindowState(window1.get())->set_window_position_managed(true); - wm::GetWindowState(window2.get())->set_window_position_managed(true); - wm::GetWindowState(window3.get())->set_window_position_managed(true); + wm::GetWindowState(window1.get())->SetWindowPositionManaged(true); + wm::GetWindowState(window2.get())->SetWindowPositionManaged(true); + wm::GetWindowState(window3.get())->SetWindowPositionManaged(true); window1->Show(); wm::ActivateWindow(window1.get()); @@ -996,8 +996,8 @@ window2->SetBounds(gfx::Rect(32, 48, 256, 512)); window1->Hide(); window2->Hide(); - wm::GetWindowState(window1.get())->set_window_position_managed(true); - wm::GetWindowState(window2.get())->set_window_position_managed(true); + wm::GetWindowState(window1.get())->SetWindowPositionManaged(true); + wm::GetWindowState(window2.get())->SetWindowPositionManaged(true); window1->Show(); EXPECT_EQ(user_pos.ToString(), window1->bounds().ToString()); window2->Show(); @@ -1027,7 +1027,7 @@ CreateTestWindowInShellWithBounds(default_bounds)); wm::WindowState* window1_state = wm::GetWindowState(window1.get()); window1->Hide(); - window1_state->set_window_position_managed(true); + window1_state->SetWindowPositionManaged(true); window1->Show(); // First window is centered. EXPECT_EQ("150,0 100x100", window1->bounds().ToString()); @@ -1035,7 +1035,7 @@ CreateTestWindowInShellWithBounds(default_bounds)); wm::WindowState* window2_state = wm::GetWindowState(window2.get()); window2->Hide(); - window2_state->set_window_position_managed(true); + window2_state->SetWindowPositionManaged(true); window2->Show(); // Auto positioning pushes windows to each sides. @@ -1072,13 +1072,13 @@ TEST_F(WorkspaceControllerTest, ToMinimizeRepositionsRemaining) { std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); wm::WindowState* window1_state = wm::GetWindowState(window1.get()); - window1_state->set_window_position_managed(true); + window1_state->SetWindowPositionManaged(true); window1->SetBounds(gfx::Rect(16, 32, 640, 320)); gfx::Rect desktop_area = window1->parent()->bounds(); std::unique_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); wm::WindowState* window2_state = wm::GetWindowState(window2.get()); - window2_state->set_window_position_managed(true); + window2_state->SetWindowPositionManaged(true); window2->SetBounds(gfx::Rect(32, 48, 256, 512)); window1_state->Minimize(); @@ -1104,12 +1104,12 @@ TEST_F(WorkspaceControllerTest, MaxToMinRepositionsRemaining) { std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); wm::WindowState* window1_state = wm::GetWindowState(window1.get()); - window1_state->set_window_position_managed(true); + window1_state->SetWindowPositionManaged(true); gfx::Rect desktop_area = window1->parent()->bounds(); std::unique_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); wm::WindowState* window2_state = wm::GetWindowState(window2.get()); - window2_state->set_window_position_managed(true); + window2_state->SetWindowPositionManaged(true); window2->SetBounds(gfx::Rect(32, 48, 256, 512)); window1_state->Maximize(); @@ -1129,12 +1129,12 @@ std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); window1->SetBounds(gfx::Rect(16, 32, 640, 320)); wm::WindowState* window1_state = wm::GetWindowState(window1.get()); - window1_state->set_window_position_managed(true); + window1_state->SetWindowPositionManaged(true); gfx::Rect desktop_area = window1->parent()->bounds(); std::unique_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); wm::WindowState* window2_state = wm::GetWindowState(window2.get()); - window2_state->set_window_position_managed(true); + window2_state->SetWindowPositionManaged(true); window2->SetBounds(gfx::Rect(32, 40, 256, 512)); // Trigger the auto window placement function by showing (and hiding) it. @@ -1165,11 +1165,11 @@ std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)); window1->SetBounds(gfx::Rect(16, 32, 640, 320)); wm::WindowState* window1_state = wm::GetWindowState(window1.get()); - window1_state->set_window_position_managed(true); + window1_state->SetWindowPositionManaged(true); gfx::Rect desktop_area = window1->parent()->bounds(); std::unique_ptr<aura::Window> window2(CreateTestWindowInShellWithId(1)); - wm::GetWindowState(window2.get())->set_window_position_managed(true); + wm::GetWindowState(window2.get())->SetWindowPositionManaged(true); window2->SetBounds(gfx::Rect(32, 40, 256, 512)); // Trigger the auto window placement function by showing (and hiding) it. @@ -1206,8 +1206,8 @@ window2->Hide(); window2->SetBounds(gfx::Rect(32, 48, 256, 512)); - wm::GetWindowState(window1.get())->set_window_position_managed(true); - wm::GetWindowState(window2.get())->set_window_position_managed(true); + wm::GetWindowState(window1.get())->SetWindowPositionManaged(true); + wm::GetWindowState(window2.get())->SetWindowPositionManaged(true); // Make sure nothing is animating. window1->layer()->GetAnimator()->StopAnimating(); window2->layer()->GetAnimator()->StopAnimating(); @@ -1308,7 +1308,7 @@ // Create an auto-positioned window. std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0)); wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->set_window_position_managed(true); + window_state->SetWindowPositionManaged(true); window->SetBounds(gfx::Rect(10, 20, 100, 200)); window->Show();
diff --git a/base/BUILD.gn b/base/BUILD.gn index 92a131a..164d39f 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -373,6 +373,8 @@ "hash.cc", "hash.h", "ios/block_types.h", + "ios/callback_counter.h", + "ios/callback_counter.mm", "ios/crb_protocol_observers.h", "ios/crb_protocol_observers.mm", "ios/device_util.h", @@ -2061,6 +2063,7 @@ "i18n/string_search_unittest.cc", "i18n/time_formatting_unittest.cc", "i18n/timezone_unittest.cc", + "ios/callback_counter_unittest.mm", "ios/crb_protocol_observers_unittest.mm", "ios/device_util_unittest.mm", "ios/weak_nsobject_unittest.mm", @@ -2767,6 +2770,17 @@ java_files = [ "test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java" ] } + java_library("base_junit_test_support") { + # Skip platform checks since Robolectric depends on requires_android targets. + bypass_platform_checks = true + testonly = true + java_files = [ "android/junit/src/org/chromium/base/metrics/test/ShadowRecordHistogram.java" ] + deps = [ + ":base_java", + "//third_party/robolectric:robolectric_all_java", + ] + } + junit_binary("base_junit_tests") { java_files = [ "android/junit/src/org/chromium/base/BaseChromiumApplicationTest.java",
diff --git a/base/android/junit/src/org/chromium/base/metrics/test/ShadowRecordHistogram.java b/base/android/junit/src/org/chromium/base/metrics/test/ShadowRecordHistogram.java new file mode 100644 index 0000000..02745482 --- /dev/null +++ b/base/android/junit/src/org/chromium/base/metrics/test/ShadowRecordHistogram.java
@@ -0,0 +1,46 @@ +// 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. + +package org.chromium.base.metrics.test; + +import android.util.Pair; + +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.annotation.Resetter; + +import org.chromium.base.metrics.RecordHistogram; + +import java.util.HashMap; + +/** + * Implementation of RecordHistogram which does not rely on native and still enables testing of + * histogram counts. + */ +@Implements(RecordHistogram.class) +public class ShadowRecordHistogram { + private static HashMap<Pair<String, Integer>, Integer> sSamples = + new HashMap<Pair<String, Integer>, Integer>(); + + @Resetter + public static void reset() { + sSamples.clear(); + } + + @Implementation + public static void recordCountHistogram(String name, int sample) { + Pair<String, Integer> key = Pair.create(name, sample); + Integer i = sSamples.get(key); + if (i == null) { + i = 0; + } + sSamples.put(key, i + 1); + } + + @Implementation + public static int getHistogramValueCountForTesting(String name, int sample) { + Integer i = sSamples.get(Pair.create(name, sample)); + return (i != null) ? i : 0; + } +}
diff --git a/ios/chrome/browser/callback_counter.h b/base/ios/callback_counter.h similarity index 100% rename from ios/chrome/browser/callback_counter.h rename to base/ios/callback_counter.h
diff --git a/ios/chrome/browser/callback_counter.mm b/base/ios/callback_counter.mm similarity index 83% rename from ios/chrome/browser/callback_counter.mm rename to base/ios/callback_counter.mm index 73b1aa26..530d0af 100644 --- a/ios/chrome/browser/callback_counter.mm +++ b/base/ios/callback_counter.mm
@@ -2,11 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ios/chrome/browser/callback_counter.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif +#include "base/ios/callback_counter.h" CallbackCounter::CallbackCounter(const FinalCallback& final_callback) : callback_count_(0U), final_callback_(final_callback) {
diff --git a/ios/chrome/browser/callback_counter_unittest.mm b/base/ios/callback_counter_unittest.mm similarity index 83% rename from ios/chrome/browser/callback_counter_unittest.mm rename to base/ios/callback_counter_unittest.mm index a58911f..04ada661 100644 --- a/ios/chrome/browser/callback_counter_unittest.mm +++ b/base/ios/callback_counter_unittest.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ios/chrome/browser/callback_counter.h" +#include "base/ios/callback_counter.h" #include "base/bind.h" #include "base/mac/bind_objc_block.h" @@ -10,17 +10,13 @@ #import "base/test/ios/wait_util.h" #include "testing/platform_test.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - using CallbackCounterTest = PlatformTest; // Tests that CallbackCounter works with 2 callbacks. TEST_F(CallbackCounterTest, Basic) { __block BOOL block_was_called = NO; scoped_refptr<CallbackCounter> callback_counter = - new CallbackCounter(base::BindBlockArc(^{ + new CallbackCounter(base::BindBlock(^{ block_was_called = YES; }));
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.cc b/base/task_scheduler/scheduler_worker_pool_impl.cc index a0e74de..5e510b1 100644 --- a/base/task_scheduler/scheduler_worker_pool_impl.cc +++ b/base/task_scheduler/scheduler_worker_pool_impl.cc
@@ -24,6 +24,13 @@ #include "base/threading/scoped_blocking_call.h" #include "base/threading/thread_restrictions.h" +#if defined(OS_WIN) +#include "base/win/scoped_com_initializer.h" +#include "base/win/scoped_windows_thread_environment.h" +#include "base/win/scoped_winrt_initializer.h" +#include "base/win/windows_version.h" +#endif // defined(OS_WIN) + namespace base { namespace internal { @@ -138,6 +145,10 @@ // returned a non-empty sequence and DidRunTask() hasn't been called yet). bool is_running_task_ = false; +#if defined(OS_WIN) + std::unique_ptr<win::ScopedWindowsThreadEnvironment> win_thread_environment_; +#endif // defined(OS_WIN) + DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDelegateImpl); }; @@ -182,7 +193,8 @@ void SchedulerWorkerPoolImpl::Start( const SchedulerWorkerPoolParams& params, - scoped_refptr<TaskRunner> service_thread_task_runner) { + scoped_refptr<TaskRunner> service_thread_task_runner, + WorkerEnvironment worker_environment) { AutoSchedulerLock auto_lock(lock_); DCHECK(workers_.empty()); @@ -191,6 +203,7 @@ initial_worker_capacity_ = worker_capacity_; suggested_reclaim_time_ = params.suggested_reclaim_time(); backward_compatibility_ = params.backward_compatibility(); + worker_environment_ = worker_environment; service_thread_task_runner_ = std::move(service_thread_task_runner); @@ -338,6 +351,18 @@ #endif } +#if defined(OS_WIN) + if (outer_->worker_environment_ == WorkerEnvironment::COM_MTA) { + if (win::GetVersion() >= win::VERSION_WIN8) { + win_thread_environment_ = std::make_unique<win::ScopedWinrtInitializer>(); + } else { + win_thread_environment_ = std::make_unique<win::ScopedCOMInitializer>( + win::ScopedCOMInitializer::kMTA); + } + DCHECK(win_thread_environment_->Succeeded()); + } +#endif // defined(OS_WIN) + DCHECK_EQ(num_tasks_since_last_wait_, 0U); PlatformThread::SetName( @@ -498,6 +523,10 @@ DCHECK(!ContainsWorker(outer_->workers_, worker)); } #endif + +#if defined(OS_WIN) + win_thread_environment_.reset(); +#endif // defined(OS_WIN) } void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::
diff --git a/base/task_scheduler/scheduler_worker_pool_impl.h b/base/task_scheduler/scheduler_worker_pool_impl.h index a469bce..617c114 100644 --- a/base/task_scheduler/scheduler_worker_pool_impl.h +++ b/base/task_scheduler/scheduler_worker_pool_impl.h
@@ -27,6 +27,7 @@ #include "base/task_scheduler/sequence.h" #include "base/task_scheduler/task.h" #include "base/time/time.h" +#include "build/build_config.h" namespace base { @@ -46,6 +47,15 @@ // This class is thread-safe. class BASE_EXPORT SchedulerWorkerPoolImpl : public SchedulerWorkerPool { public: + enum class WorkerEnvironment { + // No special worker environment required. + NONE, +#if defined(OS_WIN) + // Initialize a COM MTA on the worker. + COM_MTA, +#endif // defined(OS_WIN) + }; + // Constructs a pool without workers. // // |name| is used to label the pool's threads ("TaskScheduler" + |name| + @@ -62,9 +72,11 @@ // Creates workers following the |params| specification, allowing existing and // future tasks to run. Uses |service_thread_task_runner| to monitor for - // blocked threads in the pool. Can only be called once. CHECKs on failure. + // blocked threads in the pool. |thread_environment| Can only be called once. + // CHECKs on failure. void Start(const SchedulerWorkerPoolParams& params, - scoped_refptr<TaskRunner> service_thread_task_runner); + scoped_refptr<TaskRunner> service_thread_task_runner, + WorkerEnvironment worker_environment); // Destroying a SchedulerWorkerPoolImpl returned by Create() is not allowed in // production; it is always leaked. In tests, it can only be destroyed after @@ -229,6 +241,9 @@ // but haven't caused a worker capacity increase yet. int num_pending_may_block_workers_ = 0; + // Environment to be initialized per worker. + WorkerEnvironment worker_environment_ = WorkerEnvironment::NONE; + // Stack of idle workers. Initially, all workers are on this stack. A worker // is removed from the stack before its WakeUp() function is called and when // it receives work from GetWork() (a worker calls GetWork() when its sleep
diff --git a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc index d6074b7..06be8aa 100644 --- a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc +++ b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
@@ -43,8 +43,13 @@ #include "base/threading/thread_local_storage.h" #include "base/threading/thread_restrictions.h" #include "base/time/time.h" +#include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" +#if defined(OS_WIN) +#include "base/win/com_init_util.h" +#endif // defined(OS_WIN) + namespace base { namespace internal { namespace { @@ -85,11 +90,13 @@ ASSERT_TRUE(worker_pool_); } - void StartWorkerPool(TimeDelta suggested_reclaim_time, size_t num_workers) { + virtual void StartWorkerPool(TimeDelta suggested_reclaim_time, + size_t num_workers) { ASSERT_TRUE(worker_pool_); worker_pool_->Start( SchedulerWorkerPoolParams(num_workers, suggested_reclaim_time), - service_thread_.task_runner()); + service_thread_.task_runner(), + SchedulerWorkerPoolImpl::WorkerEnvironment::NONE); } void CreateAndStartWorkerPool(TimeDelta suggested_reclaim_time, @@ -255,6 +262,29 @@ worker_pool_->WaitForAllWorkersIdleForTesting(); } +#if defined(OS_WIN) +TEST_P(TaskSchedulerWorkerPoolImplTestParam, NoEnvironment) { + // Verify that COM is not initialized in a SchedulerWorkerPoolImpl initialized + // with SchedulerWorkerPoolImpl::WorkerEnvironment::NONE. + scoped_refptr<TaskRunner> task_runner = + CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()); + + WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + task_runner->PostTask( + FROM_HERE, BindOnce( + [](WaitableEvent* task_running) { + win::AssertComApartmentType(win::ComApartmentType::NONE); + task_running->Signal(); + }, + &task_running)); + + task_running.Wait(); + + worker_pool_->WaitForAllWorkersIdleForTesting(); +} +#endif // defined(OS_WIN) + INSTANTIATE_TEST_CASE_P(Parallel, TaskSchedulerWorkerPoolImplTestParam, ::testing::Values(test::ExecutionMode::PARALLEL)); @@ -262,6 +292,64 @@ TaskSchedulerWorkerPoolImplTestParam, ::testing::Values(test::ExecutionMode::SEQUENCED)); +#if defined(OS_WIN) + +namespace { + +class TaskSchedulerWorkerPoolImplTestCOMMTAParam + : public TaskSchedulerWorkerPoolImplTestBase, + public testing::TestWithParam<test::ExecutionMode> { + protected: + TaskSchedulerWorkerPoolImplTestCOMMTAParam() = default; + + void SetUp() override { TaskSchedulerWorkerPoolImplTestBase::SetUp(); } + + void TearDown() override { TaskSchedulerWorkerPoolImplTestBase::TearDown(); } + + private: + void StartWorkerPool(TimeDelta suggested_reclaim_time, + size_t num_workers) override { + ASSERT_TRUE(worker_pool_); + worker_pool_->Start( + SchedulerWorkerPoolParams(num_workers, suggested_reclaim_time), + service_thread_.task_runner(), + SchedulerWorkerPoolImpl::WorkerEnvironment::COM_MTA); + } + + DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplTestCOMMTAParam); +}; + +} // namespace + +TEST_P(TaskSchedulerWorkerPoolImplTestCOMMTAParam, COMMTAInitialized) { + // Verify that SchedulerWorkerPoolImpl workers have a COM MTA available. + scoped_refptr<TaskRunner> task_runner = + CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()); + + WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, + WaitableEvent::InitialState::NOT_SIGNALED); + task_runner->PostTask( + FROM_HERE, BindOnce( + [](WaitableEvent* task_running) { + win::AssertComApartmentType(win::ComApartmentType::MTA); + task_running->Signal(); + }, + &task_running)); + + task_running.Wait(); + + worker_pool_->WaitForAllWorkersIdleForTesting(); +} + +INSTANTIATE_TEST_CASE_P(Parallel, + TaskSchedulerWorkerPoolImplTestCOMMTAParam, + ::testing::Values(test::ExecutionMode::PARALLEL)); +INSTANTIATE_TEST_CASE_P(Sequenced, + TaskSchedulerWorkerPoolImplTestCOMMTAParam, + ::testing::Values(test::ExecutionMode::SEQUENCED)); + +#endif // defined(OS_WIN) + namespace { class TaskSchedulerWorkerPoolImplPostTaskBeforeStartTest @@ -694,7 +782,8 @@ "OnePolicyWorkerPool", ThreadPriority::NORMAL, &task_tracker, &delayed_task_manager); worker_pool->Start(SchedulerWorkerPoolParams(8U, TimeDelta::Max()), - service_thread_task_runner); + service_thread_task_runner, + SchedulerWorkerPoolImpl::WorkerEnvironment::NONE); ASSERT_TRUE(worker_pool); EXPECT_EQ(1U, worker_pool->NumberOfWorkersForTesting()); worker_pool->JoinForTesting(); @@ -715,7 +804,8 @@ &delayed_task_manager); worker_pool->Start( SchedulerWorkerPoolParams(worker_capacity, kReclaimTimeForCleanupTests), - service_thread_task_runner); + service_thread_task_runner, + SchedulerWorkerPoolImpl::WorkerEnvironment::NONE); ASSERT_TRUE(worker_pool); EXPECT_EQ(1U, worker_pool->NumberOfWorkersForTesting()); @@ -1237,7 +1327,8 @@ &delayed_task_manager); worker_pool.Start( SchedulerWorkerPoolParams(kWorkerCapacity, kReclaimTimeForCleanupTests), - service_thread_task_runner); + service_thread_task_runner, + SchedulerWorkerPoolImpl::WorkerEnvironment::NONE); scoped_refptr<TaskRunner> task_runner = worker_pool.CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
diff --git a/base/task_scheduler/scheduler_worker_pool_unittest.cc b/base/task_scheduler/scheduler_worker_pool_unittest.cc index 54c9c9a..818af0dd 100644 --- a/base/task_scheduler/scheduler_worker_pool_unittest.cc +++ b/base/task_scheduler/scheduler_worker_pool_unittest.cc
@@ -133,7 +133,8 @@ scheduler_worker_pool_impl->Start( SchedulerWorkerPoolParams(kNumWorkersInWorkerPool, TimeDelta::Max()), - service_thread_.task_runner()); + service_thread_.task_runner(), + SchedulerWorkerPoolImpl::WorkerEnvironment::NONE); break; } #if defined(OS_WIN)
diff --git a/base/task_scheduler/task_scheduler.cc b/base/task_scheduler/task_scheduler.cc index e01426e..29f8db4 100644 --- a/base/task_scheduler/task_scheduler.cc +++ b/base/task_scheduler/task_scheduler.cc
@@ -27,13 +27,15 @@ const SchedulerWorkerPoolParams& background_worker_pool_params_in, const SchedulerWorkerPoolParams& background_blocking_worker_pool_params_in, const SchedulerWorkerPoolParams& foreground_worker_pool_params_in, - const SchedulerWorkerPoolParams& foreground_blocking_worker_pool_params_in) + const SchedulerWorkerPoolParams& foreground_blocking_worker_pool_params_in, + SharedWorkerPoolEnvironment shared_worker_pool_environment_in) : background_worker_pool_params(background_worker_pool_params_in), background_blocking_worker_pool_params( background_blocking_worker_pool_params_in), foreground_worker_pool_params(foreground_worker_pool_params_in), foreground_blocking_worker_pool_params( - foreground_blocking_worker_pool_params_in) {} + foreground_blocking_worker_pool_params_in), + shared_worker_pool_environment(shared_worker_pool_environment_in) {} TaskScheduler::InitParams::~InitParams() = default;
diff --git a/base/task_scheduler/task_scheduler.h b/base/task_scheduler/task_scheduler.h index 6e30af0..13605151 100644 --- a/base/task_scheduler/task_scheduler.h +++ b/base/task_scheduler/task_scheduler.h
@@ -51,19 +51,31 @@ class BASE_EXPORT TaskScheduler { public: struct BASE_EXPORT InitParams { + enum class SharedWorkerPoolEnvironment { + // Use the default environment (no environment). + DEFAULT, +#if defined(OS_WIN) + // Place the worker in a COM MTA. + COM_MTA, +#endif // defined(OS_WIN) + }; + InitParams( const SchedulerWorkerPoolParams& background_worker_pool_params_in, const SchedulerWorkerPoolParams& background_blocking_worker_pool_params_in, const SchedulerWorkerPoolParams& foreground_worker_pool_params_in, const SchedulerWorkerPoolParams& - foreground_blocking_worker_pool_params_in); + foreground_blocking_worker_pool_params_in, + SharedWorkerPoolEnvironment shared_worker_pool_environment_in = + SharedWorkerPoolEnvironment::DEFAULT); ~InitParams(); SchedulerWorkerPoolParams background_worker_pool_params; SchedulerWorkerPoolParams background_blocking_worker_pool_params; SchedulerWorkerPoolParams foreground_worker_pool_params; SchedulerWorkerPoolParams foreground_blocking_worker_pool_params; + SharedWorkerPoolEnvironment shared_worker_pool_environment; }; // Destroying a TaskScheduler is not allowed in production; it is always
diff --git a/base/task_scheduler/task_scheduler_impl.cc b/base/task_scheduler/task_scheduler_impl.cc index 3901cfdc..942c844 100644 --- a/base/task_scheduler/task_scheduler_impl.cc +++ b/base/task_scheduler/task_scheduler_impl.cc
@@ -86,16 +86,28 @@ single_thread_task_runner_manager_.Start(); + const SchedulerWorkerPoolImpl::WorkerEnvironment worker_environment = +#if defined(OS_WIN) + init_params.shared_worker_pool_environment == + InitParams::SharedWorkerPoolEnvironment::COM_MTA + ? SchedulerWorkerPoolImpl::WorkerEnvironment::COM_MTA + : SchedulerWorkerPoolImpl::WorkerEnvironment::NONE; +#else + SchedulerWorkerPoolImpl::WorkerEnvironment::NONE; +#endif + worker_pools_[BACKGROUND]->Start(init_params.background_worker_pool_params, - service_thread_task_runner); + service_thread_task_runner, + worker_environment); worker_pools_[BACKGROUND_BLOCKING]->Start( init_params.background_blocking_worker_pool_params, - service_thread_task_runner); + service_thread_task_runner, worker_environment); worker_pools_[FOREGROUND]->Start(init_params.foreground_worker_pool_params, - service_thread_task_runner); + service_thread_task_runner, + worker_environment); worker_pools_[FOREGROUND_BLOCKING]->Start( init_params.foreground_blocking_worker_pool_params, - service_thread_task_runner); + service_thread_task_runner, worker_environment); } void TaskSchedulerImpl::PostDelayedTaskWithTraits(const Location& from_here,
diff --git a/build/secondary/third_party/crashpad/crashpad/minidump/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/minidump/BUILD.gn index ebc8f3b..d1c29a09 100644 --- a/build/secondary/third_party/crashpad/crashpad/minidump/BUILD.gn +++ b/build/secondary/third_party/crashpad/crashpad/minidump/BUILD.gn
@@ -20,6 +20,8 @@ } sources = [ + "minidump_byte_array_writer.cc", + "minidump_byte_array_writer.h", "minidump_context.h", "minidump_context_writer.cc", "minidump_context_writer.h",
diff --git a/build/secondary/third_party/crashpad/crashpad/snapshot/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/snapshot/BUILD.gn index 703aa550..4fca9fe 100644 --- a/build/secondary/third_party/crashpad/crashpad/snapshot/BUILD.gn +++ b/build/secondary/third_party/crashpad/crashpad/snapshot/BUILD.gn
@@ -18,6 +18,8 @@ } sources = [ + "annotation_snapshot.cc", + "annotation_snapshot.h", "capture_memory.cc", "capture_memory.h", "cpu_architecture.h", @@ -51,6 +53,7 @@ "mac/process_types.cc", "mac/process_types.h", "mac/process_types/all.proctype", + "mac/process_types/annotation.proctype", "mac/process_types/crashpad_info.proctype", "mac/process_types/crashreporterclient.proctype", "mac/process_types/custom.cc", @@ -79,6 +82,7 @@ "posix/timezone.cc", "posix/timezone.h", "process_snapshot.h", + "snapshot_constants.h", "system_snapshot.h", "thread_snapshot.h", "unloaded_module_snapshot.cc",
diff --git a/build/secondary/third_party/crashpad/crashpad/test/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/test/BUILD.gn index a194928d..5027ad36d 100644 --- a/build/secondary/third_party/crashpad/crashpad/test/BUILD.gn +++ b/build/secondary/third_party/crashpad/crashpad/test/BUILD.gn
@@ -9,6 +9,8 @@ "errors.h", "file.cc", "file.h", + "filesystem.cc", + "filesystem.h", "gtest_death_check.h", "gtest_disabled.cc", "gtest_disabled.h",
diff --git a/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn b/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn index 65367b93..fea27982 100644 --- a/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn +++ b/build/secondary/third_party/crashpad/crashpad/util/BUILD.gn
@@ -326,8 +326,6 @@ "file/file_io_test.cc", "file/file_reader_test.cc", "file/filesystem_test.cc", - "file/filesystem_test_util.cc", - "file/filesystem_test_util.h", "file/string_file_test.cc", "mac/launchd_test.mm", "mac/mac_util_test.mm",
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc index 89a92d7..5758caf 100644 --- a/cc/paint/paint_op_buffer.cc +++ b/cc/paint/paint_op_buffer.cc
@@ -206,10 +206,12 @@ static const SerializeFunction g_serialize_functions[kNumOpTypes] = {TYPES(M)}; #undef M -using DeserializeFunction = PaintOp* (*)(const volatile void* input, - size_t input_size, - void* output, - size_t output_size); +using DeserializeFunction = + PaintOp* (*)(const volatile void* input, + size_t input_size, + void* output, + size_t output_size, + const PaintOp::DeserializeOptions& options); #define M(T) &T::Deserialize, static const DeserializeFunction g_deserialize_functions[kNumOpTypes] = { @@ -599,7 +601,8 @@ PaintOp* AnnotateOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(AnnotateOp)); AnnotateOp* op = new (output) AnnotateOp; @@ -619,7 +622,8 @@ PaintOp* ClipPathOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ClipPathOp)); ClipPathOp* op = new (output) ClipPathOp; @@ -639,7 +643,8 @@ PaintOp* ClipRectOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ClipRectOp)); return SimpleDeserialize<ClipRectOp>(input, input_size, output, output_size); } @@ -647,7 +652,8 @@ PaintOp* ClipRRectOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ClipRRectOp)); return SimpleDeserialize<ClipRRectOp>(input, input_size, output, output_size); } @@ -655,7 +661,8 @@ PaintOp* ConcatOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ConcatOp)); auto* op = SimpleDeserialize<ConcatOp>(input, input_size, output, output_size); @@ -667,7 +674,8 @@ PaintOp* DrawColorOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawColorOp)); return SimpleDeserialize<DrawColorOp>(input, input_size, output, output_size); } @@ -675,7 +683,8 @@ PaintOp* DrawDRRectOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawDRRectOp)); DrawDRRectOp* op = new (output) DrawDRRectOp; @@ -694,7 +703,8 @@ PaintOp* DrawImageOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawImageOp)); DrawImageOp* op = new (output) DrawImageOp; @@ -714,7 +724,8 @@ PaintOp* DrawImageRectOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawImageRectOp)); DrawImageRectOp* op = new (output) DrawImageRectOp; @@ -735,7 +746,8 @@ PaintOp* DrawIRectOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawIRectOp)); DrawIRectOp* op = new (output) DrawIRectOp; @@ -753,7 +765,8 @@ PaintOp* DrawLineOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawLineOp)); DrawLineOp* op = new (output) DrawLineOp; @@ -774,7 +787,8 @@ PaintOp* DrawOvalOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawOvalOp)); DrawOvalOp* op = new (output) DrawOvalOp; @@ -792,7 +806,8 @@ PaintOp* DrawPathOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawPathOp)); DrawPathOp* op = new (output) DrawPathOp; @@ -810,7 +825,8 @@ PaintOp* DrawRecordOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { // TODO(enne): these must be flattened and not sent directly. // TODO(enne): could also consider caching these service side. return nullptr; @@ -819,7 +835,8 @@ PaintOp* DrawRectOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawRectOp)); DrawRectOp* op = new (output) DrawRectOp; @@ -837,7 +854,8 @@ PaintOp* DrawRRectOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawRRectOp)); DrawRRectOp* op = new (output) DrawRRectOp; @@ -855,7 +873,8 @@ PaintOp* DrawTextBlobOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(DrawTextBlobOp)); DrawTextBlobOp* op = new (output) DrawTextBlobOp; @@ -875,7 +894,8 @@ PaintOp* NoopOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(NoopOp)); return SimpleDeserialize<NoopOp>(input, input_size, output, output_size); } @@ -883,7 +903,8 @@ PaintOp* RestoreOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(RestoreOp)); return SimpleDeserialize<RestoreOp>(input, input_size, output, output_size); } @@ -891,7 +912,8 @@ PaintOp* RotateOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(RotateOp)); return SimpleDeserialize<RotateOp>(input, input_size, output, output_size); } @@ -899,7 +921,8 @@ PaintOp* SaveOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(SaveOp)); return SimpleDeserialize<SaveOp>(input, input_size, output, output_size); } @@ -907,7 +930,8 @@ PaintOp* SaveLayerOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(SaveLayerOp)); SaveLayerOp* op = new (output) SaveLayerOp; @@ -925,7 +949,8 @@ PaintOp* SaveLayerAlphaOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(SaveLayerAlphaOp)); return SimpleDeserialize<SaveLayerAlphaOp>(input, input_size, output, output_size); @@ -934,7 +959,8 @@ PaintOp* ScaleOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(ScaleOp)); return SimpleDeserialize<ScaleOp>(input, input_size, output, output_size); @@ -943,7 +969,8 @@ PaintOp* SetMatrixOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(SetMatrixOp)); auto* op = SimpleDeserialize<SetMatrixOp>(input, input_size, output, output_size); @@ -955,7 +982,8 @@ PaintOp* TranslateOp::Deserialize(const volatile void* input, size_t input_size, void* output, - size_t output_size) { + size_t output_size, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(TranslateOp)); return SimpleDeserialize<TranslateOp>(input, input_size, output, output_size); } @@ -1268,7 +1296,8 @@ size_t input_size, void* output, size_t output_size, - size_t* read_bytes) { + size_t* read_bytes, + const DeserializeOptions& options) { DCHECK_GE(output_size, sizeof(LargestPaintOp)); uint32_t first_word = reinterpret_cast<const volatile uint32_t*>(input)[0]; @@ -1282,7 +1311,8 @@ if (type > static_cast<uint8_t>(PaintOpType::LastPaintOpType)) return nullptr; *read_bytes = skip; - return g_deserialize_functions[type](input, skip, output, output_size); + return g_deserialize_functions[type](input, skip, output, output_size, + options); } // static
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h index 4446c76..0568c5bf 100644 --- a/cc/paint/paint_op_buffer.h +++ b/cc/paint/paint_op_buffer.h
@@ -54,7 +54,8 @@ static size_t Serialize(const PaintOp* op, void* memory, size_t size, \ const SerializeOptions& options); \ static PaintOp* Deserialize(const volatile void* input, size_t input_size, \ - void* output, size_t output_size); + void* output, size_t output_size, \ + const DeserializeOptions& options); enum class PaintOpType : uint8_t { Annotate, @@ -114,6 +115,8 @@ ImageDecodeCache* decode_cache = nullptr; }; + struct DeserializeOptions {}; + // Subclasses should provide a static Serialize() method called from here. // If the op can be serialized to |memory| in no more than |size| bytes, // then return the number of bytes written. If it won't fit, return 0. @@ -132,7 +135,8 @@ size_t input_size, void* output, size_t output_size, - size_t* read_bytes); + size_t* read_bytes, + const DeserializeOptions& options); // For draw ops, returns true if a conservative bounding rect can be provided // for the op.
diff --git a/cc/paint/paint_op_buffer_fuzzer.cc b/cc/paint/paint_op_buffer_fuzzer.cc index 6a7cca6b..b296570 100644 --- a/cc/paint/paint_op_buffer_fuzzer.cc +++ b/cc/paint/paint_op_buffer_fuzzer.cc
@@ -27,6 +27,7 @@ SkCanvas* canvas = surface->getCanvas(); cc::PlaybackParams params(nullptr, canvas->getTotalMatrix()); + cc::PaintOp::DeserializeOptions deserialize_options; // Need 4 bytes to be able to read the type/skip. while (size >= 4) { @@ -38,9 +39,9 @@ static_cast<char*>(base::AlignedAlloc( sizeof(cc::LargestPaintOp), cc::PaintOpBuffer::PaintOpAlign))); size_t bytes_read = 0; - cc::PaintOp* deserialized_op = - cc::PaintOp::Deserialize(data, size, deserialized.get(), - sizeof(cc::LargestPaintOp), &bytes_read); + cc::PaintOp* deserialized_op = cc::PaintOp::Deserialize( + data, size, deserialized.get(), sizeof(cc::LargestPaintOp), &bytes_read, + deserialize_options); if (!deserialized_op) break;
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc index af65cb8..56bdab6 100644 --- a/cc/paint/paint_op_buffer_unittest.cc +++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -1359,9 +1359,9 @@ if (!remaining_) return; - deserialized_op_ = - PaintOp::Deserialize(current_, remaining_, data_.get(), - sizeof(LargestPaintOp), &last_bytes_read_); + deserialized_op_ = PaintOp::Deserialize(current_, remaining_, data_.get(), + sizeof(LargestPaintOp), + &last_bytes_read_, options); } const void* input_ = nullptr; @@ -1369,6 +1369,7 @@ size_t input_size_ = 0u; size_t remaining_ = 0u; size_t last_bytes_read_ = 0u; + PaintOp::DeserializeOptions options; std::unique_ptr<char, base::AlignedFreeDeleter> data_; PaintOp* deserialized_op_ = nullptr; }; @@ -2153,6 +2154,7 @@ static constexpr size_t kOutputOpSize = kBufferBytesPerOp; std::unique_ptr<char, base::AlignedFreeDeleter> deserialize_buffer_( static_cast<char*>(base::AlignedAlloc(kOutputOpSize, kAlign))); + PaintOp::DeserializeOptions deserialize_options; size_t op_idx = 0; for (PaintOpBuffer::Iterator iter(&buffer_); iter; ++iter, ++op_idx) { @@ -2175,7 +2177,7 @@ size_t bytes_read = 0; PaintOp* written = PaintOp::Deserialize(current, read_size, deserialize_buffer_.get(), - kOutputOpSize, &bytes_read); + kOutputOpSize, &bytes_read, deserialize_options); // Skips are only valid if they are aligned. if (read_size >= skip && read_size % kAlign == 0) { @@ -2203,6 +2205,7 @@ static_cast<char*>(base::AlignedAlloc(kSize, kAlign))); std::unique_ptr<char, base::AlignedFreeDeleter> output_( static_cast<char*>(base::AlignedAlloc(kSize, kAlign))); + PaintOp::DeserializeOptions deserialize_options; PaintOpBuffer buffer; buffer.push<DrawColorOp>(SK_ColorMAGENTA, SkBlendMode::kSrc); @@ -2211,14 +2214,15 @@ PaintOp* op = *iter; ASSERT_TRUE(op); - PaintOp::SerializeOptions options; - size_t bytes_written = op->Serialize(input_.get(), kSize, options); + PaintOp::SerializeOptions serialize_options; + size_t bytes_written = op->Serialize(input_.get(), kSize, serialize_options); ASSERT_GT(bytes_written, 0u); // can deserialize from exactly the right size size_t bytes_read = 0; - PaintOp* success = PaintOp::Deserialize(input_.get(), bytes_written, - output_.get(), kSize, &bytes_read); + PaintOp* success = + PaintOp::Deserialize(input_.get(), bytes_written, output_.get(), kSize, + &bytes_read, deserialize_options); ASSERT_TRUE(success); EXPECT_EQ(bytes_written, bytes_read); success->DestroyThis(); @@ -2227,20 +2231,20 @@ // (the DeserializationFailures test above tests if the skip is lying) for (size_t i = 0; i < bytes_written - 1; ++i) EXPECT_FALSE(PaintOp::Deserialize(input_.get(), i, output_.get(), kSize, - &bytes_read)); + &bytes_read, deserialize_options)); // unaligned skips fail to deserialize PaintOp* serialized = reinterpret_cast<PaintOp*>(input_.get()); EXPECT_EQ(0u, serialized->skip % kAlign); serialized->skip -= 1; EXPECT_FALSE(PaintOp::Deserialize(input_.get(), bytes_written, output_.get(), - kSize, &bytes_read)); + kSize, &bytes_read, deserialize_options)); serialized->skip += 1; // bogus types fail to deserialize serialized->type = static_cast<uint8_t>(PaintOpType::LastPaintOpType) + 1; EXPECT_FALSE(PaintOp::Deserialize(input_.get(), bytes_written, output_.get(), - kSize, &bytes_read)); + kSize, &bytes_read, deserialize_options)); } // Test that deserializing invalid SkClipOp enums fails silently. @@ -2271,18 +2275,19 @@ SkClipOp bad_clip_max = static_cast<SkClipOp>(~static_cast<uint32_t>(0)); buffer.push<ClipRectOp>(test_rects[1], bad_clip_max, false); - PaintOp::SerializeOptions options; + PaintOp::SerializeOptions serialize_options; + PaintOp::DeserializeOptions deserialize_options; int op_idx = 0; for (PaintOpBuffer::Iterator iter(&buffer); iter; ++iter) { const PaintOp* op = *iter; size_t bytes_written = - op->Serialize(serialized.get(), buffer_size, options); + op->Serialize(serialized.get(), buffer_size, serialize_options); ASSERT_GT(bytes_written, 0u); size_t bytes_read = 0; - PaintOp* written = - PaintOp::Deserialize(serialized.get(), bytes_written, - deserialized.get(), buffer_size, &bytes_read); + PaintOp* written = PaintOp::Deserialize(serialized.get(), bytes_written, + deserialized.get(), buffer_size, + &bytes_read, deserialize_options); // First op should succeed. Other ops with bad enums should // serialize correctly but fail to deserialize due to the bad // SkClipOp enum. @@ -2351,18 +2356,19 @@ buffer.push<DrawRectOp>(test_rects[i % test_rects.size()], flags); } - PaintOp::SerializeOptions options; + PaintOp::SerializeOptions serialize_options; + PaintOp::DeserializeOptions deserialize_options; int op_idx = 0; for (PaintOpBuffer::Iterator iter(&buffer); iter; ++iter) { const PaintOp* op = *iter; size_t bytes_written = - op->Serialize(serialized.get(), buffer_size, options); + op->Serialize(serialized.get(), buffer_size, serialize_options); ASSERT_GT(bytes_written, 0u); size_t bytes_read = 0; - PaintOp* written = - PaintOp::Deserialize(serialized.get(), bytes_written, - deserialized.get(), buffer_size, &bytes_read); + PaintOp* written = PaintOp::Deserialize(serialized.get(), bytes_written, + deserialized.get(), buffer_size, + &bytes_read, deserialize_options); // First two ops should succeed. Other ops with bad enums should // serialize correctly but fail to deserialize due to the bad // SkBlendMode enum. @@ -2406,19 +2412,20 @@ buffer.push<SaveLayerOp>(&bad_rect, &test_flags[0]); buffer.push<SaveLayerAlphaOp>(&bad_rect, test_uint8s[0], true); - PaintOp::SerializeOptions options; + PaintOp::SerializeOptions serialize_options; + PaintOp::DeserializeOptions deserialize_options; // Every op should serialize but fail to deserialize due to the bad rect. int op_idx = 0; for (PaintOpBuffer::Iterator iter(&buffer); iter; ++iter) { const PaintOp* op = *iter; size_t bytes_written = - op->Serialize(serialized.get(), buffer_size, options); + op->Serialize(serialized.get(), buffer_size, serialize_options); ASSERT_GT(bytes_written, 0u); size_t bytes_read = 0; - PaintOp* written = - PaintOp::Deserialize(serialized.get(), bytes_written, - deserialized.get(), buffer_size, &bytes_read); + PaintOp* written = PaintOp::Deserialize(serialized.get(), bytes_written, + deserialized.get(), buffer_size, + &bytes_read, deserialize_options); EXPECT_FALSE(written) << "op: " << op_idx; ++op_idx; }
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 556bb3a..2ede08c 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -400,6 +400,7 @@ "$google_play_services_package:google_play_services_cast_java", "//base:base_java", "//base:base_java_test_support", + "//base:base_junit_test_support", "//chrome/android/webapk/libs/client:client_java", "//chrome/android/webapk/libs/common:common_java", "//chrome/android/webapk/test:junit_test_support",
diff --git a/chrome/android/java/res/drawable/site_explore_page_indicator.xml b/chrome/android/java/res/drawable/site_explore_page_indicator.xml deleted file mode 100644 index 1c559f8..0000000 --- a/chrome/android/java/res/drawable/site_explore_page_indicator.xml +++ /dev/null
@@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright 2015 The Chromium Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. --> - -<selector xmlns:android="http://schemas.android.com/apk/res/android" - android:exitFadeDuration="@android:integer/config_mediumAnimTime" - android:enterFadeDuration="@android:integer/config_mediumAnimTime"> -<item android:state_selected="true"> - <shape android:shape="oval"> - <solid android:color="@color/google_grey_600"/> - <size android:width="8dp" android:height="8dp"/> - </shape> -</item> -<item> - <shape android:shape="oval"> - <solid android:color="@color/google_grey_400"/> - <size android:width="8dp" android:height="8dp"/> - </shape> -</item> -</selector> \ No newline at end of file
diff --git a/chrome/android/java/res/layout/suggestions_site_explore.xml b/chrome/android/java/res/layout/suggestions_site_explore.xml deleted file mode 100644 index 5fa541d1..0000000 --- a/chrome/android/java/res/layout/suggestions_site_explore.xml +++ /dev/null
@@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. --> - -<org.chromium.chrome.browser.suggestions.SiteExploreViewPager - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:chrome="http://schemas.android.com/apk/res-auto" - android:id="@+id/site_explore_pager" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="@dimen/tile_grid_layout_padding_start" - android:layout_marginEnd="@dimen/tile_grid_layout_padding_end" - android:layout_gravity="center_horizontal" - android:paddingBottom="20dp"> - - <android.support.design.widget.TabLayout - android:id="@+id/tab_layout" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="top" - android:clipToPadding="false" - chrome:tabTextAppearance="@android:style/TextAppearance.Widget.TabWidget" - chrome:tabGravity="fill" - chrome:tabMode="scrollable" - /> - - <org.chromium.chrome.browser.suggestions.SiteExplorePageIndicatorView - android:id="@+id/tile_section_indicator_view" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="bottom" - android:paddingTop="10dp" - android:orientation="horizontal" - android:gravity="center_horizontal" - /> - </org.chromium.chrome.browser.suggestions.SiteExploreViewPager>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index 102969d..bc6718e8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -215,7 +215,6 @@ public static final String PWA_PERSISTENT_NOTIFICATION = "PwaPersistentNotification"; public static final String READER_MODE_IN_CCT = "ReaderModeInCCT"; public static final String SERVICE_WORKER_PAYMENT_APPS = "ServiceWorkerPaymentApps"; - public static final String SITE_EXPLORATION_UI = "SiteExplorationUi"; public static final String SITE_NOTIFICATION_CHANNELS = "SiteNotificationChannels"; public static final String SOUND_CONTENT_SETTING = "SoundContentSetting"; public static final String SPANNABLE_INLINE_AUTOCOMPLETE = "SpannableInlineAutocomplete";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java index 267131ac..8c8ce5dd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
@@ -162,6 +162,11 @@ TimeUnit.HOURS.toMillis(1), TimeUnit.DAYS.toMillis(30), TimeUnit.MILLISECONDS, 50); } + /** Records to UMA the count of old "WebAPK update request" files. */ + public static void recordNumberOfStaleWebApkUpdateRequestFiles(int count) { + RecordHistogram.recordCountHistogram("WebApk.Update.NumStaleUpdateRequestFiles", count); + } + /** * Log necessary disk usage and cache size UMAs when WebAPK installation fails. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java index f8203c8..dce01fb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
@@ -20,7 +20,6 @@ import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView; import org.chromium.chrome.browser.ntp.snippets.SnippetsConfig; import org.chromium.chrome.browser.suggestions.SiteSection; -import org.chromium.chrome.browser.suggestions.SuggestionsConfig; import org.chromium.chrome.browser.suggestions.TileGridLayout; /** @@ -119,10 +118,7 @@ } /** - * @return different result depending on whether {@link - * SuggestionsConfig#useSitesExplorationUi()} is enabled. When the sites exploration feature is - * enabled, this will return the enclosing view group of the explore layout file. Otherwise, - * this method will return a {@link TileGridLayout}. + * @return the embedded {@link TileGridLayout}. */ public ViewGroup getSiteSectionView() { return mSiteSectionView; @@ -147,19 +143,11 @@ mLogoSpacer.setVisibility(View.GONE); mSearchBoxSpacer.setVisibility(View.GONE); - if (!SuggestionsConfig.useSitesExplorationUi()) { - // Remove the extra spacing before measuring because it might not be needed anymore. - ((TileGridLayout) mSiteSectionView).setExtraVerticalSpacing(0); - } + // Remove the extra spacing before measuring because it might not be needed anymore. + ((TileGridLayout) mSiteSectionView).setExtraVerticalSpacing(0); super.onMeasure(widthMeasureSpec, heightMeasureSpec); - if (SuggestionsConfig.useSitesExplorationUi()) { - // We want to skip vertical spacing when site explore is enabled, but we still need - // to call onMeasure() before returning. - return; - } - boolean hasSpaceForPeekingCard = false; int spaceToFill = mParentViewportHeight - mPeekingCardHeight - mTabStripHeight; @NTPLayoutResult int layoutResult;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteExplorePageIndicatorView.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteExplorePageIndicatorView.java deleted file mode 100644 index c5d4297..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteExplorePageIndicatorView.java +++ /dev/null
@@ -1,110 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.suggestions; - -import android.content.Context; -import android.database.DataSetObserver; -import android.support.annotation.Nullable; -import android.support.v4.view.ViewPager; -import android.util.AttributeSet; -import android.view.View; -import android.widget.ImageView; -import android.widget.LinearLayout; - -import org.chromium.chrome.R; -import org.chromium.chrome.browser.util.ViewUtils; - -/** - * Page indicator view for a {@link ViewPager}. It has to be inserted as a child of the - * {@link ViewPager}. After this, it will read the number of pages, display that many dots and - * highlight the dot of the selected tab. - */ -public class SiteExplorePageIndicatorView - extends LinearLayout implements ViewPager.OnPageChangeListener { - private static final int SPACE_BETWEEN_INDICATORS_DP = 8; - - private ViewPager mViewPager; - private DataSetObserver mDataSetObserver; - private int mCurrentSelectedPosition; - - public SiteExplorePageIndicatorView(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - mDataSetObserver = new DataSetObserver() { - @Override - public void onChanged() { - addPageIndicators(); - } - }; - } - - @Override - public void onPageScrolled(int i, float v, int i1) {} - - @Override - public void onPageSelected(int newPosition) { - // Switch the highlighted dot to the one corresponding to the newly selected page. - View currentSelectedView = getChildAt(mCurrentSelectedPosition); - View newSelectedView = getChildAt(newPosition); - - currentSelectedView.setSelected(false); - newSelectedView.setSelected(true); - - mCurrentSelectedPosition = newPosition; - } - - @Override - public void onPageScrollStateChanged(int i) {} - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - - mViewPager = (ViewPager) getParent(); - - mViewPager.addOnPageChangeListener(this); - mViewPager.getAdapter().registerDataSetObserver(mDataSetObserver); - - ((ViewPager.LayoutParams) getLayoutParams()).isDecor = true; - - addPageIndicators(); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - - mViewPager.removeOnPageChangeListener(this); - mViewPager.getAdapter().unregisterDataSetObserver(mDataSetObserver); - mViewPager = null; - } - - private void addPageIndicators() { - int numberOfPages = mViewPager.getAdapter().getCount(); - mCurrentSelectedPosition = mViewPager.getCurrentItem(); - - removeAllViews(); - - int indicatorSideMarginPx = ViewUtils.dpToPx(getContext(), SPACE_BETWEEN_INDICATORS_DP / 2); - for (int i = 0; i < numberOfPages; i++) { - ImageView singlePageIndicatorView = new ImageView(getContext()); - - singlePageIndicatorView.setBackgroundResource(R.drawable.site_explore_page_indicator); - singlePageIndicatorView.setAdjustViewBounds(true); - - // Set space on both sides of the indicator. - LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); - lp.setMargins(indicatorSideMarginPx, 0, indicatorSideMarginPx, 0); - singlePageIndicatorView.setLayoutParams(lp); - - if (i == mCurrentSelectedPosition) { - singlePageIndicatorView.setSelected(true); - } - - addView(singlePageIndicatorView); - } - } - -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteExploreViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteExploreViewHolder.java deleted file mode 100644 index 19781cb..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteExploreViewHolder.java +++ /dev/null
@@ -1,187 +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. - -package org.chromium.chrome.browser.suggestions; - -import android.content.Context; -import android.support.annotation.Nullable; -import android.support.v4.view.PagerAdapter; -import android.util.SparseArray; -import android.view.View; -import android.view.ViewGroup; - -import org.chromium.chrome.R; - -import java.util.List; - -/** - * A view holder for the Explore UI. - */ -public class SiteExploreViewHolder extends SiteSectionViewHolder { - private final int mMaxTileColumns; - private SiteExploreViewPager mSiteExploreViewPager; - private SiteExploreViewHolder.ExploreSectionsAdapter mAdapter; - - public SiteExploreViewHolder(ViewGroup view, int maxTileColumns) { - super(view); - mMaxTileColumns = maxTileColumns; - mSiteExploreViewPager = itemView.findViewById(R.id.site_explore_pager); - - mAdapter = new ExploreSectionsAdapter(itemView.getContext()); - mSiteExploreViewPager.setAdapter(mAdapter); - } - - @Override - public void refreshData() { - mAdapter.updateTiles(mTileGroup.getTileSections()); - } - - @Nullable - @Override - protected TileView findTileView(SiteSuggestion data) { - return mAdapter.findTileView(data); - } - - /** - * Adapter for the Explore UI view holder. - */ - public class ExploreSectionsAdapter extends PagerAdapter { - private final Context mContext; - /** - * We use the category {@link TileSectionType} as key. The value is the layout used for - * that category in the {@link SiteExploreViewPager}. At any one time there will be at most - * three layouts stored in this array - the one that is currently shown on the screen and - * the two on either side of it. - */ - private SparseArray<TileGridLayout> mTileSectionLayouts; - - /** - * The latest tile sections which came with an update from - * {@link #updateTiles(SparseArray)}. The key is the section id and the value is the - * list of tiles within this section. See {@link TileSectionType}. - */ - private SparseArray<List<Tile>> mLatestTileSections; - - public ExploreSectionsAdapter(Context context) { - mContext = context; - mTileSectionLayouts = new SparseArray<TileGridLayout>(); - } - - @Override - public View instantiateItem(ViewGroup container, int position) { - List<Tile> tileSectionList = mLatestTileSections.valueAt(position); - if (tileSectionList == null) return null; - - @TileSectionType - int sectionType = mTileGroup.getTileSections().keyAt(position); - TileGridLayout layout = mTileSectionLayouts.get(sectionType); - if (layout == null) { - layout = new TileGridLayout(mContext, null); - - layout.setMaxRows(1); - layout.setMaxColumns(mMaxTileColumns); - mTileRenderer.renderTileSection( - tileSectionList, layout, mTileGroup.getTileSetupDelegate()); - mTileSectionLayouts.put(sectionType, layout); - } - - if (sectionType == TileSectionType.PERSONALIZED) { - mTileGroup.notifyTilesRendered(); - } - - container.addView(layout); - return layout; - } - - @Override - public void destroyItem(ViewGroup container, int position, Object object) { - container.removeView((View) object); - mTileSectionLayouts.remove(mTileSectionLayouts.keyAt(position)); - } - - @Override - public int getCount() { - return mLatestTileSections == null ? 0 : mLatestTileSections.size(); - } - - @Override - public String getPageTitle(int position) { - @TileSectionType - int sectionType = (mLatestTileSections.keyAt(position)); - int stringRes; - switch (sectionType) { - case TileSectionType.PERSONALIZED: - stringRes = R.string.ntp_sites_exploration_category_personalized_title; - break; - case TileSectionType.SOCIAL: - stringRes = R.string.ntp_sites_exploration_category_social_title; - break; - case TileSectionType.ENTERTAINMENT: - stringRes = R.string.ntp_sites_exploration_category_entertainment_title; - break; - case TileSectionType.NEWS: - stringRes = R.string.ntp_sites_exploration_category_news_title; - break; - case TileSectionType.ECOMMERCE: - stringRes = R.string.ntp_sites_exploration_category_ecommerce_title; - break; - case TileSectionType.TOOLS: - stringRes = R.string.ntp_sites_exploration_category_tools_title; - break; - case TileSectionType.TRAVEL: - stringRes = R.string.ntp_sites_exploration_category_travel_title; - break; - case TileSectionType.UNKNOWN: - default: - stringRes = R.string.ntp_sites_exploration_category_other_title; - break; - } - - return mContext.getResources().getString(stringRes); - } - - @Override - public boolean isViewFromObject(View view, Object object) { - return view == object; - } - - @Nullable - public TileView findTileView(SiteSuggestion suggestion) { - TileGridLayout layout = mTileSectionLayouts.get(suggestion.sectionType); - if (layout == null) return null; - return layout.getTileView(suggestion); - } - - /** - * Updates the data set for the adapter. We use this method instead of directly reading - * data from the {@link TileGroup} because this allows us to update the tiles directly - * and prevents inconsistencies with the data. - * - * @param freshTileSections The new information for the tile sections. - */ - public void updateTiles(SparseArray<List<Tile>> freshTileSections) { - mLatestTileSections = freshTileSections; - - // Get the category IDs of the section layouts which are already rendered. - int[] layoutCategoryIds = new int[mTileSectionLayouts.size()]; - for (int i = 0; i < mTileSectionLayouts.size(); i++) { - layoutCategoryIds[i] = mTileSectionLayouts.keyAt(i); - } - - for (@TileSectionType int layoutCategoryId : layoutCategoryIds) { - if (freshTileSections.get(layoutCategoryId) == null) { - // Remove the section layout from the view pager because it is not in the - // freshly fetched sections. - mSiteExploreViewPager.removeView(mTileSectionLayouts.get(layoutCategoryId)); - mTileSectionLayouts.remove(layoutCategoryId); - continue; - } - mTileRenderer.renderTileSection(freshTileSections.get(layoutCategoryId), - mTileSectionLayouts.get(layoutCategoryId), - mTileGroup.getTileSetupDelegate()); - } - notifyDataSetChanged(); - } - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteExploreViewPager.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteExploreViewPager.java deleted file mode 100644 index bcabdbba..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteExploreViewPager.java +++ /dev/null
@@ -1,60 +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. - -package org.chromium.chrome.browser.suggestions; - -import android.content.Context; -import android.support.v4.view.ViewPager; -import android.util.AttributeSet; -import android.view.View; - -/** - * View Pager for the Site Explore UI. This is needed in order to correctly calculate the height - * of this section on {@link #onMeasure(int, int)}. - */ -public class SiteExploreViewPager extends ViewPager { - public SiteExploreViewPager(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // We need to override this method to support the wrap_content behaviour that is not handled - // by the base implementation. - - // We need to call super to let the ViewPager initialize its children pages first. This will - // call ViewPagerAdapter.initializeItem(), which will add the pages. However, this - // does not measure the heights of the children. That's why we need to measure the - // children's heights explicitly after that. - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - int neededHeight = 0; - - // Get the required height from the view pager's children. ViewPager decors (e.g. TabLayout) - // and ViewPager pages are both ViewPager children. The decors come first. We add up the - // heights of all decors and the height of the first page to get the required height for the - // view pager. We assume that all pages have the same height. - for (int i = 0; i < getChildCount(); i++) { - View child = getChildAt(i); - child.measure( - widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - - neededHeight += child.getMeasuredHeight(); - - // Break the loop when we see the first page (non decor view). - if (!((ViewPager.LayoutParams) child.getLayoutParams()).isDecor) break; - } - - // Take into account vertical padding. - neededHeight += getPaddingTop() + getPaddingBottom(); - - // Create a new measure specification with the newly calculated height. - heightMeasureSpec = MeasureSpec.makeMeasureSpec(neededHeight, MeasureSpec.EXACTLY); - - // TODO(galinap): Restrict view pager's width to tile_grid_layout_max_width in NTP. - - // Super method has to be called again so the new specs are treated as exact measurements. - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSection.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSection.java index 42bc315..9223e908 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSection.java
@@ -49,9 +49,7 @@ } public static SiteSectionViewHolder createViewHolder(ViewGroup view, UiConfig uiConfig) { - return SuggestionsConfig.useSitesExplorationUi() - ? new SiteExploreViewHolder(view, MAX_TILE_COLUMNS) - : new TileGridViewHolder(view, getMaxTileRows(), MAX_TILE_COLUMNS, uiConfig); + return new TileGridViewHolder(view, getMaxTileRows(), MAX_TILE_COLUMNS, uiConfig); } public SiteSection(SuggestionsUiDelegate uiDelegate, ContextMenuManager contextMenuManager, @@ -127,9 +125,6 @@ @LayoutRes private static int getLayout() { - if (SuggestionsConfig.useSitesExplorationUi()) { - return R.layout.suggestions_site_explore; - } if (FeatureUtilities.isChromeHomeEnabled()) { return R.layout.suggestions_site_tile_grid_modern; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java index 02b1c3b..54bda01 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java
@@ -44,13 +44,6 @@ } /** - * @return Whether to use the Sites exploration UI to display the site suggestions. - */ - public static boolean useSitesExplorationUi() { - return ChromeFeatureList.isEnabled(ChromeFeatureList.SITE_EXPLORATION_UI); - } - - /** * @param resources The resources to fetch the color from. * @return The background color for the suggestions sheet content. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeHomeSurveyController.java b/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeHomeSurveyController.java index d27c8e4..a911350 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeHomeSurveyController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeHomeSurveyController.java
@@ -32,12 +32,13 @@ * Class that controls if and when to show surveys related to the Chrome Home experiment. */ public class ChromeHomeSurveyController { - static final String SURVEY_INFO_BAR_DISPLAYED = "chrome_home_survey_info_bar_displayed"; - static final long ONE_WEEK_IN_MILLIS = 604800000L; + public static final String SURVEY_INFO_BAR_DISPLAYED = "chrome_home_survey_info_bar_displayed"; + public static final String PARAM_NAME = "survey_override_site_id"; - private static final String PARAM_NAME = "survey_override_site_id"; private static final String TRIAL_NAME = "ChromeHome"; + static final long ONE_WEEK_IN_MILLIS = 604800000L; + private TabModelSelector mTabModelSelector; private ChromeHomeSurveyController() { @@ -80,10 +81,10 @@ } private boolean doesUserQualifyForSurvey() { - if (!isUMAEnabled()) return false; if (CommandLine.getInstance().hasSwitch(ChromeSwitches.CHROME_HOME_FORCE_ENABLE_SURVEY)) { return true; } + if (!isUMAEnabled()) return false; if (AccessibilityUtil.isAccessibilityEnabled()) return false; if (hasInfoBarBeenDisplayed()) return false; if (!FeatureUtilities.isChromeHomeEnabled()) return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java index 98aba2b2..b8f21c4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
@@ -1188,7 +1188,11 @@ } private void onStateLoaded() { - if (mObserver != null) mObserver.onStateLoaded(); + if (mObserver != null) { + // mergeState() starts an AsyncTask to call this and this calls + // onTabStateInitialized which should be called from the UI thread. + ThreadUtils.runOnUiThread( () -> mObserver.onStateLoaded() ); + } } private void loadNextTab() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java index 5227372..0080ce9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
@@ -14,7 +14,6 @@ import org.chromium.base.ContextUtils; import org.chromium.base.Log; -import org.chromium.base.PathUtils; import org.chromium.base.VisibleForTesting; import org.chromium.blink_public.platform.WebDisplayMode; import org.chromium.chrome.browser.ShortcutHelper; @@ -34,9 +33,6 @@ public class WebappDataStorage { private static final String TAG = "WebappDataStorage"; - /** Path of subdirectory within cache directory which contains data for pending updates. */ - static final String UPDATE_DIRECTORY_PATH = "webapk/update"; - static final String SHARED_PREFS_FILE_PREFIX = "webapp_"; static final String KEY_SPLASH_ICON = "splash_icon"; static final String KEY_LAST_USED = "last_used"; @@ -501,9 +497,7 @@ * SharedPreferences. */ String createAndSetUpdateRequestFilePath(WebApkInfo info) { - String filePath = - new File(new File(PathUtils.getCacheDirectory(), UPDATE_DIRECTORY_PATH), info.id()) - .getPath(); + String filePath = WebappDirectoryManager.getWebApkUpdateFilePathForStorage(this).getPath(); mPreferences.edit().putString(KEY_PENDING_UPDATE_FILE_PATH, filePath).apply(); return filePath; } @@ -534,6 +528,14 @@ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } + /** + * Returns whether a check for whether the Web Manifest needs to be updated has occurred in the + * last {@link numMillis} milliseconds. + */ + boolean wasCheckForUpdatesDoneInLastMs(long numMillis) { + return (sClock.currentTimeMillis() - getLastCheckForWebManifestUpdateTime()) < numMillis; + } + /** Returns whether we should check for update. */ boolean shouldCheckForUpdate() { long checkUpdatesInterval =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDirectoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDirectoryManager.java index 6accda76..c915453 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDirectoryManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDirectoryManager.java
@@ -19,8 +19,10 @@ import org.chromium.base.ContextUtils; import org.chromium.base.FileUtils; import org.chromium.base.Log; +import org.chromium.base.PathUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.document.DocumentUtils; +import org.chromium.chrome.browser.metrics.WebApkUma; import java.io.File; import java.util.HashSet; @@ -35,11 +37,16 @@ * which each WebappActivity using a directory named either for its Webapp's ID in Document mode, * or the index of the WebappActivity if it is a subclass of the WebappManagedActivity class (which * are used in pre-L devices to allow multiple WebappActivities launching). + * + * Also records metrics about files in the "WebAPK update" directory. */ public class WebappDirectoryManager { protected static final String WEBAPP_DIRECTORY_NAME = "WebappActivity"; private static final String TAG = "WebappDirectoryManag"; + /** Path of subdirectory within cache directory which contains data for pending updates. */ + private static final String UPDATE_DIRECTORY_PATH = "webapk/update"; + /** Whether or not the class has already started trying to clean up obsolete directories. */ private static final AtomicBoolean sMustCleanUpOldDirectories = new AtomicBoolean(true); @@ -62,6 +69,8 @@ mCleanupTask = new AsyncTask<Void, Void, Void>() { @Override protected final Void doInBackground(Void... params) { + recordNumberOfStaleWebApkUpdateRequestFiles(); + Set<File> directoriesToDelete = new HashSet<File>(); directoriesToDelete.add(getWebappDirectory(context, currentWebappId)); @@ -136,6 +145,29 @@ } } + /** Records to UMA the count of old "WebAPK update request" files. */ + private void recordNumberOfStaleWebApkUpdateRequestFiles() { + File updateDirectory = getWebApkUpdateDirectory(); + int count = 0; + File[] children = updateDirectory.listFiles(); + if (children != null) { + for (File child : children) { + WebappDataStorage storage = + WebappRegistry.getInstance().getWebappDataStorage(child.getName()); + if (storage == null) { + ++count; + continue; + } + + if (!storage.wasCheckForUpdatesDoneInLastMs(TimeUnit.DAYS.toMillis(1L))) { + ++count; + } + } + } + + WebApkUma.recordNumberOfStaleWebApkUpdateRequestFiles(count); + } + /** * Returns the directory for a web app, creating it if necessary. * @param webappId ID for the web app. Used as a subdirectory name. @@ -163,6 +195,16 @@ return context.getDir(WEBAPP_DIRECTORY_NAME, Context.MODE_PRIVATE); } + /** Returns the directory for "WebAPK update" files. Does not create the directory. */ + static final File getWebApkUpdateDirectory() { + return new File(PathUtils.getCacheDirectory(), UPDATE_DIRECTORY_PATH); + } + + /** Returns the path for the "WebAPK update" file for the given {@link WebappDataStorage}. */ + static final File getWebApkUpdateFilePathForStorage(WebappDataStorage storage) { + return new File(getWebApkUpdateDirectory(), storage.getId()); + } + /** Returns a Set of Intents for all Chrome tasks currently known by the ActivityManager. */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) protected Set<Intent> getBaseIntentsForAllTasks() {
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 3532fb62..d13c64c5 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -547,30 +547,6 @@ <message name="IDS_SAFE_BROWSING_SUMMARY" desc="Summary for safe browsing."> Protect you and your device from dangerous sites </message> - <message name="IDS_NTP_SITES_EXPLORATION_CATEGORY_PERSONALIZED_TITLE" desc="In the Sites Explore UI, title of the Personalized category."> - Personalized - </message> - <message name="IDS_NTP_SITES_EXPLORATION_CATEGORY_NEWS_TITLE" desc="In the Sites Explore UI, title of the News category."> - News - </message> - <message name="IDS_NTP_SITES_EXPLORATION_CATEGORY_SOCIAL_TITLE" desc="In the Sites Explore UI, title of the Social category."> - Social - </message> - <message name="IDS_NTP_SITES_EXPLORATION_CATEGORY_ENTERTAINMENT_TITLE" desc="In the Sites Explore UI, title of the Entertainment category."> - Entertainment - </message> - <message name="IDS_NTP_SITES_EXPLORATION_CATEGORY_ECOMMERCE_TITLE" desc="In the Sites Explore UI, title of the Ecommerce category."> - E-commerce - </message> - <message name="IDS_NTP_SITES_EXPLORATION_CATEGORY_TOOLS_TITLE" desc="In the Sites Explore UI, title of the Tools category."> - Tools - </message> - <message name="IDS_NTP_SITES_EXPLORATION_CATEGORY_TRAVEL_TITLE" desc="In the Sites Explore UI, title of the Travel category."> - Travel - </message> - <message name="IDS_NTP_SITES_EXPLORATION_CATEGORY_OTHER_TITLE" desc="In the Sites Explore UI, title of the Unknown category."> - Other - </message> <message name="IDS_NETWORK_PREDICTIONS_TITLE" desc="Title of a setting in Chrome settings. Followed by a body that describes what pages are downloaded. If setting is turned on, Chrome will download certain pages to the user’s phone automatically for offline reading. “Download” is a verb, imperative. "> Automatically download pages </message>
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index ca6c1938..3a9f6d2 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -1066,8 +1066,6 @@ "java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java", "java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java", "java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java", - "java/src/org/chromium/chrome/browser/suggestions/SiteExploreViewHolder.java", - "java/src/org/chromium/chrome/browser/suggestions/SiteExploreViewPager.java", "java/src/org/chromium/chrome/browser/suggestions/SiteSection.java", "java/src/org/chromium/chrome/browser/suggestions/SiteSectionViewHolder.java", "java/src/org/chromium/chrome/browser/suggestions/SiteSuggestion.java", @@ -1087,7 +1085,6 @@ "java/src/org/chromium/chrome/browser/suggestions/TileRenderer.java", "java/src/org/chromium/chrome/browser/suggestions/TileView.java", "java/src/org/chromium/chrome/browser/suggestions/NavigationRecorder.java", - "java/src/org/chromium/chrome/browser/suggestions/SiteExplorePageIndicatorView.java", "java/src/org/chromium/chrome/browser/suggestions/SuggestionsDependencyFactory.java", "java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegate.java", "java/src/org/chromium/chrome/browser/suggestions/SuggestionsNavigationDelegateImpl.java", @@ -1924,6 +1921,7 @@ "junit/src/org/chromium/chrome/browser/survey/ChromeHomeSurveyControllerTest.java", "junit/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java", "junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java", + "junit/src/org/chromium/chrome/browser/webapps/MockWebappDataStorageClockRule.java", "junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java", "junit/src/org/chromium/chrome/browser/webapps/WebappDirectoryManagerTest.java", "junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java",
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/MockWebappDataStorageClockRule.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/MockWebappDataStorageClockRule.java new file mode 100644 index 0000000..7964b3a2 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/MockWebappDataStorageClockRule.java
@@ -0,0 +1,47 @@ +// 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. + +package org.chromium.chrome.browser.webapps; + +import org.junit.rules.ExternalResource; + +/** Test rule to set clock WebappDataStorage uses for getting the current time. */ +class MockWebappDataStorageClockRule extends ExternalResource { + private static class MockClock extends WebappDataStorage.Clock { + /** + * Not zero so that callers of {@link currentTimeMillis()} substracting from the current + * time get reasonable behavior. + */ + private long mCurrentTime = 10000000000L; + + public void advance(long millis) { + mCurrentTime += millis; + } + + @Override + public long currentTimeMillis() { + return mCurrentTime; + } + } + + private MockClock mClock = new MockClock(); + + public void advance(long millis) { + mClock.advance(millis); + } + + public long currentTimeMillis() { + return mClock.currentTimeMillis(); + } + + @Override + protected void before() throws Throwable { + WebappDataStorage.setClockForTests(mClock); + } + + @Override + protected void after() { + WebappDataStorage.setClockForTests(new WebappDataStorage.Clock()); + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java index 1238c421..93e0f10 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
@@ -57,6 +57,9 @@ @Rule public DisableHistogramsRule mDisableHistogramsRule = new DisableHistogramsRule(); + @Rule + public MockWebappDataStorageClockRule mClockRule = new MockWebappDataStorageClockRule(); + private static final String WEBAPK_PACKAGE_NAME = "org.chromium.webapk.test_package"; private static final String UNBOUND_WEBAPK_PACKAGE_NAME = "com.webapk.test_package"; @@ -79,21 +82,6 @@ /** Different name than the one used in {@link defaultManifestData()}. */ private static final String DIFFERENT_NAME = "Different Name"; - /** {@link WebappDataStorage#Clock} subclass which enables time to be manually advanced. */ - private static class MockClock extends WebappDataStorage.Clock { - // 0 has a special meaning: {@link WebappDataStorage#TIMESTAMP_INVALID}. - private long mTimeMillis = 1; - - public void advance(long millis) { - mTimeMillis += millis; - } - - @Override - public long currentTimeMillis() { - return mTimeMillis; - } - } - /** Mock {@link WebApkUpdateDataFetcher}. */ private static class TestWebApkUpdateDataFetcher extends WebApkUpdateDataFetcher { private boolean mStarted; @@ -203,8 +191,6 @@ public long backgroundColor; } - private MockClock mClock; - private static String getWebApkId(String packageName) { return WebApkConstants.WEBAPK_ID_PREFIX + packageName; } @@ -370,7 +356,7 @@ private boolean checkUpdateNeededForFetchedManifest( ManifestData androidManifestData, ManifestData fetchedManifestData) { registerWebApk(WEBAPK_PACKAGE_NAME, androidManifestData, CURRENT_SHELL_APK_VERSION); - mClock.advance(WebappDataStorage.UPDATE_INTERVAL); + mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL); TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME)); @@ -388,8 +374,6 @@ CommandLine.init(null); registerWebApk(WEBAPK_PACKAGE_NAME, defaultManifestData(), CURRENT_SHELL_APK_VERSION); - mClock = new MockClock(); - WebappDataStorage.setClockForTests(mClock); WebappRegistry.getInstance().register(getWebApkId(WEBAPK_PACKAGE_NAME), new WebappRegistry.FetchWebappDataStorageCallback() { @@ -410,7 +394,7 @@ */ @Test public void testCheckOnNextLaunchIfClosePriorToFirstPageLoad() { - mClock.advance(WebappDataStorage.UPDATE_INTERVAL); + mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL); { TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME)); @@ -446,8 +430,8 @@ */ @Test public void testUpdateNotNeeded() { - long initialTime = mClock.currentTimeMillis(); - mClock.advance(WebappDataStorage.UPDATE_INTERVAL); + long initialTime = mClockRule.currentTimeMillis(); + mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL); TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME)); @@ -471,7 +455,7 @@ public void testMarkUpdateAsSucceededIfUpdateNoLongerNeeded() { WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME); storage.updateDidLastWebApkUpdateRequestSucceed(false); - mClock.advance(WebappDataStorage.RETRY_UPDATE_DURATION); + mClockRule.advance(WebappDataStorage.RETRY_UPDATE_DURATION); TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME)); @@ -482,7 +466,7 @@ assertTrue(storage.getDidLastWebApkUpdateRequestSucceed()); assertEquals( - mClock.currentTimeMillis(), storage.getLastWebApkUpdateRequestCompletionTime()); + mClockRule.currentTimeMillis(), storage.getLastWebApkUpdateRequestCompletionTime()); } /** @@ -491,7 +475,7 @@ */ @Test public void testMarkUpdateAsFailedIfClosePriorToUpdateCompleting() { - mClock.advance(WebappDataStorage.UPDATE_INTERVAL); + mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL); TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME)); @@ -506,7 +490,7 @@ WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME); assertFalse(storage.getDidLastWebApkUpdateRequestSucceed()); assertEquals( - mClock.currentTimeMillis(), storage.getLastWebApkUpdateRequestCompletionTime()); + mClockRule.currentTimeMillis(), storage.getLastWebApkUpdateRequestCompletionTime()); } /** @@ -515,7 +499,7 @@ */ @Test public void testPendingUpdateFileDeletedAfterUpdateCompletion() { - mClock.advance(WebappDataStorage.UPDATE_INTERVAL); + mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL); WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME); TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage); @@ -540,7 +524,7 @@ */ @Test public void testFileDeletedIfStoreWebApkUpdateRequestToFileFails() { - mClock.advance(WebappDataStorage.UPDATE_INTERVAL); + mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL); WebappDataStorage storage = getStorage(WEBAPK_PACKAGE_NAME); TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(storage); @@ -571,7 +555,7 @@ @Test public void testShellApkOutOfDateNoWebManifest() { registerWebApk(WEBAPK_PACKAGE_NAME, defaultManifestData(), CURRENT_SHELL_APK_VERSION - 1); - mClock.advance(WebappDataStorage.UPDATE_INTERVAL); + mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL); TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME)); @@ -594,7 +578,7 @@ @Test public void testShellApkOutOfDateStillHasWebManifest() { registerWebApk(WEBAPK_PACKAGE_NAME, defaultManifestData(), CURRENT_SHELL_APK_VERSION - 1); - mClock.advance(WebappDataStorage.UPDATE_INTERVAL); + mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL); TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME)); @@ -618,7 +602,7 @@ */ @Test public void testStartUrlRedirectsToPageWithUpdatedWebManifest() { - mClock.advance(WebappDataStorage.UPDATE_INTERVAL); + mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL); TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME)); @@ -654,7 +638,7 @@ */ @Test public void testStartUrlRedirectsToPageWithUnchangedWebManifest() { - mClock.advance(WebappDataStorage.UPDATE_INTERVAL); + mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL); TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(getStorage(WEBAPK_PACKAGE_NAME)); @@ -684,7 +668,7 @@ ManifestData androidManifestData = defaultManifestData(); registerWebApk(UNBOUND_WEBAPK_PACKAGE_NAME, androidManifestData, CURRENT_SHELL_APK_VERSION); - mClock.advance(WebappDataStorage.UPDATE_INTERVAL); + mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL); TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(getStorage(UNBOUND_WEBAPK_PACKAGE_NAME)); @@ -856,13 +840,13 @@ assertTrue(updateManager.updateRequested()); tryCompletingUpdate(updateManager, WebApkInstallResult.FAILURE); - mClock.advance(1); + mClockRule.advance(1); updateIfNeeded(updateManager); assertFalse(updateManager.updateCheckStarted()); // A previous update request was made for the current ShellAPK version. A WebAPK update // should be requested after the regular delay. - mClock.advance(WebappDataStorage.UPDATE_INTERVAL - 1); + mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL - 1); updateIfNeeded(updateManager); assertTrue(updateManager.updateCheckStarted()); onGotManifestData(updateManager, defaultManifestData());
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java index b719405..164a94a 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
@@ -15,6 +15,7 @@ import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RuntimeEnvironment; @@ -25,7 +26,6 @@ import org.chromium.base.test.util.Feature; import org.chromium.blink_public.platform.WebDisplayMode; import org.chromium.chrome.browser.ShortcutHelper; -import org.chromium.chrome.browser.webapps.WebappDataStorage.Clock; import org.chromium.testing.local.BackgroundShadowAsyncTask; import org.chromium.testing.local.LocalRobolectricTestRunner; @@ -38,6 +38,8 @@ @RunWith(LocalRobolectricTestRunner.class) @Config(manifest = Config.NONE, shadows = {BackgroundShadowAsyncTask.class}) public class WebappDataStorageTest { + @Rule + public MockWebappDataStorageClockRule mClockRule = new MockWebappDataStorageClockRule(); private SharedPreferences mSharedPreferences; private boolean mCallbackCalled; @@ -56,27 +58,6 @@ } } - private static class TestClock extends WebappDataStorage.Clock { - private long mCurrentTime; - - public TestClock(long currentTime) { - updateTime(currentTime); - } - - public void advance(long millis) { - mCurrentTime += millis; - } - - public void updateTime(long currentTime) { - mCurrentTime = currentTime; - } - - @Override - public long currentTimeMillis() { - return mCurrentTime; - } - } - @Before public void setUp() throws Exception { ContextUtils.initApplicationContextForTests(RuntimeEnvironment.application); @@ -92,7 +73,6 @@ @After public void tearDown() { mSharedPreferences.edit().clear().apply(); - WebappDataStorage.setClockForTests(new Clock()); } @Test @@ -181,9 +161,6 @@ @Test @Feature({"Webapp"}) public void testWasLaunchedRecently() throws Exception { - final TestClock clock = new TestClock(System.currentTimeMillis()); - WebappDataStorage.setClockForTests(clock); - // Opening a data storage doesn't count as a launch. WebappDataStorage storage = WebappDataStorage.open("test"); assertTrue(!storage.wasUsedRecently()); @@ -320,14 +297,13 @@ public void testCheckUpdateMoreFrequentlyIfUpdateFails() { assertTrue(WebappDataStorage.UPDATE_INTERVAL > WebappDataStorage.RETRY_UPDATE_DURATION); - final TestClock clock = new TestClock(System.currentTimeMillis()); - WebappDataStorage storage = getStorage(clock); + WebappDataStorage storage = getStorage(); storage.updateTimeOfLastWebApkUpdateRequestCompletion(); storage.updateDidLastWebApkUpdateRequestSucceed(true); assertFalse(storage.shouldCheckForUpdate()); - clock.advance(WebappDataStorage.RETRY_UPDATE_DURATION); + mClockRule.advance(WebappDataStorage.RETRY_UPDATE_DURATION); assertFalse(storage.shouldCheckForUpdate()); // Advance all of the time stamps. @@ -336,7 +312,7 @@ storage.updateDidLastWebApkUpdateRequestSucceed(false); assertFalse(storage.shouldCheckForUpdate()); - clock.advance(WebappDataStorage.RETRY_UPDATE_DURATION); + mClockRule.advance(WebappDataStorage.RETRY_UPDATE_DURATION); assertTrue(storage.shouldCheckForUpdate()); // Verifies that {@link WebappDataStorage#shouldCheckForUpdate()} returns true because the @@ -354,13 +330,13 @@ public void testRegularCheckIntervalIfNoPriorWebApkUpdate() { assertTrue(WebappDataStorage.UPDATE_INTERVAL > WebappDataStorage.RETRY_UPDATE_DURATION); - final TestClock clock = new TestClock(System.currentTimeMillis()); - WebappDataStorage storage = getStorage(clock); + WebappDataStorage storage = getStorage(); assertFalse(storage.shouldCheckForUpdate()); - clock.advance(WebappDataStorage.RETRY_UPDATE_DURATION); + mClockRule.advance(WebappDataStorage.RETRY_UPDATE_DURATION); assertFalse(storage.shouldCheckForUpdate()); - clock.advance(WebappDataStorage.UPDATE_INTERVAL - WebappDataStorage.RETRY_UPDATE_DURATION); + mClockRule.advance( + WebappDataStorage.UPDATE_INTERVAL - WebappDataStorage.RETRY_UPDATE_DURATION); assertTrue(storage.shouldCheckForUpdate()); } @@ -373,20 +349,18 @@ public void testRelaxedUpdates() { assertTrue(WebappDataStorage.RELAXED_UPDATE_INTERVAL > WebappDataStorage.UPDATE_INTERVAL); - final TestClock clock = new TestClock(System.currentTimeMillis()); - WebappDataStorage storage = getStorage(clock); + WebappDataStorage storage = getStorage(); storage.setRelaxedUpdates(true); - clock.advance(WebappDataStorage.UPDATE_INTERVAL); + mClockRule.advance(WebappDataStorage.UPDATE_INTERVAL); assertFalse(storage.shouldCheckForUpdate()); - clock.advance( + mClockRule.advance( WebappDataStorage.RELAXED_UPDATE_INTERVAL - WebappDataStorage.UPDATE_INTERVAL); assertTrue(storage.shouldCheckForUpdate()); } - private WebappDataStorage getStorage(TestClock clock) { - WebappDataStorage.setClockForTests(clock); + private WebappDataStorage getStorage() { WebappDataStorage storage = WebappDataStorage.open("test"); // Done when WebAPK is registered in {@link WebApkActivity}.
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDirectoryManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDirectoryManagerTest.java index 26b9ff4..6b5b49d 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDirectoryManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDirectoryManagerTest.java
@@ -12,15 +12,20 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; import org.robolectric.shadows.ShadowLooper; +import org.chromium.base.ContextUtils; import org.chromium.base.FileUtils; +import org.chromium.base.PathUtils; import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.metrics.test.ShadowRecordHistogram; import org.chromium.base.test.util.Feature; import org.chromium.testing.local.CustomShadowAsyncTask; import org.chromium.testing.local.LocalRobolectricTestRunner; @@ -29,13 +34,18 @@ import java.io.File; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.TimeUnit; /** * Tests that directories for WebappActivities are managed correctly. */ @RunWith(LocalRobolectricTestRunner.class) -@Config(manifest = Config.NONE, shadows = {CustomShadowAsyncTask.class}) +@Config(manifest = Config.NONE, + shadows = {CustomShadowAsyncTask.class, ShadowRecordHistogram.class}) public class WebappDirectoryManagerTest { + @Rule + public MockWebappDataStorageClockRule mClockRule = new MockWebappDataStorageClockRule(); + private static final String WEBAPP_ID_1 = "webapp_1"; private static final String WEBAPP_ID_2 = "webapp_2"; private static final String WEBAPP_ID_3 = "webapp_3"; @@ -52,32 +62,47 @@ } } + /** Deletes directory and all of its children. Recreates empty directory in its place. */ + private void deleteDirectoryAndRecreate(File f) { + FileUtils.recursivelyDeleteFile(f); + Assert.assertTrue(f.mkdirs()); + } + private Context mContext; private TestWebappDirectoryManager mWebappDirectoryManager; @Before public void setUp() throws Exception { - ThreadUtils.setThreadAssertsDisabledForTesting(true); - RecordHistogram.setDisabledForTests(true); mContext = RuntimeEnvironment.application; + ContextUtils.initApplicationContextForTests(mContext); + ThreadUtils.setThreadAssertsDisabledForTesting(true); + PathUtils.setPrivateDataDirectorySuffix("chrome"); mWebappDirectoryManager = new TestWebappDirectoryManager(); mWebappDirectoryManager.resetForTesting(); // Set up directories. - File baseDirectory = mContext.getDataDir(); - FileUtils.recursivelyDeleteFile(baseDirectory); - Assert.assertTrue(baseDirectory.mkdirs()); + deleteDirectoryAndRecreate(mContext.getDataDir()); FileUtils.recursivelyDeleteFile(mWebappDirectoryManager.getBaseWebappDirectory(mContext)); + deleteDirectoryAndRecreate(mContext.getCodeCacheDir()); } @After public void tearDown() throws Exception { FileUtils.recursivelyDeleteFile(mContext.getDataDir()); + FileUtils.recursivelyDeleteFile(mContext.getCodeCacheDir()); FileUtils.recursivelyDeleteFile(mWebappDirectoryManager.getBaseWebappDirectory(mContext)); - RecordHistogram.setDisabledForTests(false); ThreadUtils.setThreadAssertsDisabledForTesting(false); } + public void registerWebapp(String webappId) { + WebappRegistry.getInstance().register( + webappId, new WebappRegistry.FetchWebappDataStorageCallback() { + @Override + public void onWebappDataStorageRetrieved(WebappDataStorage storage) {} + }); + ShadowApplication.getInstance().runBackgroundTasks(); + } + @Test @Feature({"Webapps"}) public void testDeletesOwnDirectory() throws Exception { @@ -181,6 +206,68 @@ Assert.assertTrue(nonWebappDirectory.exists()); } + /** + * Test that WebApk.Update.NumStaleUpdateRequestFiles counts "update request" files for WebAPKs + * which have been uninstalled. + */ + @Test + @Feature({"Webapps"}) + public void testCountsUpdateFilesForUninstalledWebApks() throws Exception { + File directory1 = new File(WebappDirectoryManager.getWebApkUpdateDirectory(), WEBAPK_ID_1); + directory1.mkdirs(); + File directory2 = new File(WebappDirectoryManager.getWebApkUpdateDirectory(), WEBAPK_ID_2); + directory2.mkdirs(); + + // No entry for WEBAPK_ID_1 and WEBAPK_ID_2 in WebappRegistry because the WebAPKs have been + // uninstalled. + + runCleanup(); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + "WebApk.Update.NumStaleUpdateRequestFiles", 2)); + } + + /** + * Test that WebApk.Update.NumStaleUpdateRequestFiles counts "update request" files for WebAPKs + * for which an update was requested a long time ago. + */ + @Test + @Feature({"Webapps"}) + public void testCountsOldWebApkUpdateFiles() throws Exception { + File directory = new File(mWebappDirectoryManager.getWebApkUpdateDirectory(), WEBAPK_ID_1); + directory.mkdirs(); + registerWebapp(WEBAPK_ID_1); + WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorage(WEBAPK_ID_1); + storage.updateTimeOfLastCheckForUpdatedWebManifest(); + mClockRule.advance(TimeUnit.DAYS.toMillis(30)); + + runCleanup(); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + "WebApk.Update.NumStaleUpdateRequestFiles", 1)); + } + + /** + * Test that WebApk.Update.NumStaleUpdateRequestFiles does not count "update request" files for + * WebAPKs for which an update was recently requested. There is a 1-23 hour delay between + * a WebAPK update being scheduled to the WebAPK being updated. + */ + @Test + @Feature({"Webapps"}) + public void testDoesNotCountFilesForNewlyScheduledUpdates() throws Exception { + File directory = new File(mWebappDirectoryManager.getWebApkUpdateDirectory(), WEBAPK_ID_1); + directory.mkdirs(); + registerWebapp(WEBAPK_ID_1); + WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorage(WEBAPK_ID_1); + storage.updateTimeOfLastCheckForUpdatedWebManifest(); + mClockRule.advance(1); + + runCleanup(); + Assert.assertEquals(0, + RecordHistogram.getHistogramValueCountForTesting( + "WebApk.Update.NumStaleUpdateRequestFiles", 1)); + } + private void runCleanup() throws Exception { mWebappDirectoryManager.cleanUpDirectories(mContext, WEBAPP_ID_1); ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
diff --git a/chrome/app/md_extensions_strings.grdp b/chrome/app/md_extensions_strings.grdp index 995be14d..19c08e1 100644 --- a/chrome/app/md_extensions_strings.grdp +++ b/chrome/app/md_extensions_strings.grdp
@@ -199,6 +199,41 @@ <message name="IDS_MD_EXTENSIONS_TYPE_A_SHORTCUT" desc="The prompt to the user to enter a keyboard shortcut in order to assign it to an extension."> Type a shortcut </message> +<if expr="is_macosx"> + <message name="IDS_MD_EXTENSIONS_SHORTCUT_INSTRUCTIONS" desc="Instructions explaining that shortcuts must start with either the Control, Alt, or Command key."> + Shortcuts must start with Ctrl, Alt, or Command + </message> + <message name="IDS_MD_EXTENSIONS_INCLUDE_START_MODIFIER" desc="Error message explaining that shortcuts must start with either the Control, Alt, or Command key."> + Include Ctrl, Alt, or Command + </message> +</if> +<if expr="chromeos"> + <message name="IDS_MD_EXTENSIONS_SHORTCUT_INSTRUCTIONS" desc="Instructions explaining that shortcuts must start with either the Control, Alt, or Search key."> + Shortcuts must start with Ctrl, Alt, or Search + </message> + <message name="IDS_MD_EXTENSIONS_INCLUDE_START_MODIFIER" desc="Error message explaining that shortcuts must start with either the Control, Alt, or Search key."> + Include Ctrl, Alt, or Search + </message> +</if> +<if expr="is_macosx or chromeos"> + <message name="IDS_MD_EXTENSIONS_TOO_MANY_MODIFIERS" desc="Error message explaining not to use so many modifiers in a shortcut."> + Invalid combination + </message> +</if> +<if expr="not is_macosx and not chromeos"> + <message name="IDS_MD_EXTENSIONS_SHORTCUT_INSTRUCTIONS" desc="Instructions explaining that shortcuts must start with either the Control key or the Alt key."> + Shortcuts must start with either Ctrl or Alt + </message> + <message name="IDS_MD_EXTENSIONS_INCLUDE_START_MODIFIER" desc="Error message explaining that shortcuts must start with either the Control key or the Alt key."> + Include either Ctrl or Alt + </message> + <message name="IDS_MD_EXTENSIONS_TOO_MANY_MODIFIERS" desc="Error message explaining not to use both Ctrl and Alt in a shortcut."> + Either, not both Ctrl and Alt + </message> +</if> +<message name="IDS_MD_EXTENSIONS_NEED_CHARACTER" desc="Error message explaining that a shortcut needs a character. This is only shown if a valid modifier is already entered."> + Need a character +</message> <if expr="chromeos"> <!-- Extensions Kiosk apps --> <message name="IDS_MD_EXTENSIONS_MANAGE_KIOSK_APP" desc="Label of the button to bring up kiosk management overlay on chrome extensions page.">
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog.cc b/chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog.cc index 3317fc2..784385e 100644 --- a/chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog.cc +++ b/chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog.cc
@@ -398,15 +398,9 @@ return; // the |url| has been handled. } - // Otherwise, retrieve icons of the activities. First, swap |handler| elements - // to ensure Chrome is visible in the UI by default. Since this function is - // for handling external protocols, Chrome is rarely in the list, but if the - // |url| is intent: with fallback or geo:, for example, it may be. - std::pair<size_t, size_t> indices; - if (ArcNavigationThrottle::IsSwapElementsNeeded(handlers, &indices)) - std::swap(handlers[indices.first], handlers[indices.second]); - - // Then request the icons. + // Otherwise, retrieve icons of the activities. Since this function is for + // handling external protocols, Chrome is rarely in the list, but if the |url| + // is intent: with fallback or geo:, for example, it may be. std::vector<ArcIntentHelperBridge::ActivityName> activities; for (const auto& handler : handlers) { activities.emplace_back(handler->package_name, handler->activity_name);
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.cc b/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.cc index 288169a3..5832439 100644 --- a/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.cc +++ b/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.cc
@@ -432,26 +432,6 @@ } // static -bool ArcNavigationThrottle::IsSwapElementsNeeded( - const std::vector<mojom::IntentHandlerInfoPtr>& handlers, - std::pair<size_t, size_t>* out_indices) { - size_t chrome_app_index = 0; - for (size_t i = 0; i < handlers.size(); ++i) { - if (ArcIntentHelperBridge::IsIntentHelperPackage( - handlers[i]->package_name)) { - chrome_app_index = i; - break; - } - } - if (chrome_app_index < ArcNavigationThrottle::kMaxAppResults) - return false; - - *out_indices = std::make_pair(ArcNavigationThrottle::kMaxAppResults - 1, - chrome_app_index); - return true; -} - -// static void ArcNavigationThrottle::AsyncShowIntentPickerBubble(const Browser* browser, const GURL& url) { arc::ArcServiceManager* arc_service_manager = arc::ArcServiceManager::Get();
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h b/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h index c983a88..c1b4608 100644 --- a/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h +++ b/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h
@@ -111,14 +111,6 @@ static bool IsAppAvailable( const std::vector<mojom::IntentHandlerInfoPtr>& handlers); - // Swaps Chrome app with any app in row |kMaxAppResults-1| iff its index is - // bigger, thus ensuring the user can always see Chrome without scrolling. - // When swap is needed, fills |out_indices| and returns true. If |handlers| - // do not have Chrome, returns false. - static bool IsSwapElementsNeeded( - const std::vector<mojom::IntentHandlerInfoPtr>& handlers, - std::pair<size_t, size_t>* out_indices); - static bool IsAppAvailableForTesting( const std::vector<mojom::IntentHandlerInfoPtr>& handlers); static size_t FindPreferredAppForTesting(
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle_unittest.cc b/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle_unittest.cc index ac6fe71..f216b058 100644 --- a/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle_unittest.cc +++ b/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle_unittest.cc
@@ -229,55 +229,4 @@ ArcNavigationThrottle::CloseReason::PREFERRED_ACTIVITY_FOUND)); } -TEST(ArcNavigationThrottleTest, TestIsSwapElementsNeeded) { - std::pair<size_t, size_t> indices; - for (size_t i = 1; i <= ArcNavigationThrottle::kMaxAppResults; ++i) { - // When Chrome is the first element, swap is unnecessary. - std::vector<mojom::IntentHandlerInfoPtr> handlers = CreateArray(i, 0); - EXPECT_FALSE( - ArcNavigationThrottle::IsSwapElementsNeeded(handlers, &indices)) - << i; - - // When Chrome is within the first |kMaxAppResults| elements, swap is - // unnecessary. - handlers = CreateArray(i, i - 1); - EXPECT_FALSE( - ArcNavigationThrottle::IsSwapElementsNeeded(handlers, &indices)) - << i; - } - - for (size_t i = ArcNavigationThrottle::kMaxAppResults + 1; - i < ArcNavigationThrottle::kMaxAppResults * 2; ++i) { - // When Chrome is within the first |kMaxAppResults| elements, swap is - // unnecessary. - std::vector<mojom::IntentHandlerInfoPtr> handlers = CreateArray(i, 0); - EXPECT_FALSE( - ArcNavigationThrottle::IsSwapElementsNeeded(handlers, &indices)) - << i; - - // When Chrome is the |kMaxAppResults|-th element, swap is unnecessary. - handlers = CreateArray(i, ArcNavigationThrottle::kMaxAppResults - 1); - EXPECT_FALSE( - ArcNavigationThrottle::IsSwapElementsNeeded(handlers, &indices)) - << i; - - // When Chrome is not within the first |kMaxAppResults| elements, swap is - // necessary. - handlers = CreateArray(i, i - 1); - indices.first = indices.second = 0; - EXPECT_TRUE(ArcNavigationThrottle::IsSwapElementsNeeded(handlers, &indices)) - << i; - EXPECT_EQ(ArcNavigationThrottle::kMaxAppResults - 1u, indices.first) << i; - EXPECT_EQ(i - 1, indices.second) << i; - } - - for (size_t i = 0; i <= ArcNavigationThrottle::kMaxAppResults * 2; ++i) { - // When Chrome does not exist in |handlers|, swap is unnecessary. - std::vector<mojom::IntentHandlerInfoPtr> handlers = CreateArray(i, i); - EXPECT_FALSE( - ArcNavigationThrottle::IsSwapElementsNeeded(handlers, &indices)) - << i; - } -} - } // namespace arc
diff --git a/chrome/browser/media/webrtc/webrtc_text_log_handler.cc b/chrome/browser/media/webrtc/webrtc_text_log_handler.cc index eacf2ee6..e30c4fd0 100644 --- a/chrome/browser/media/webrtc/webrtc_text_log_handler.cc +++ b/chrome/browser/media/webrtc/webrtc_text_log_handler.cc
@@ -46,6 +46,7 @@ using content::BrowserThread; namespace { + std::string FormatMetaDataAsLogMessage(const MetaDataMap& meta_data) { std::string message; for (auto& kv : meta_data) { @@ -90,6 +91,14 @@ return address.ToString(); #endif } + +net::NetworkInterfaceList GetNetworkInterfaceList() { + net::NetworkInterfaceList network_list; + net::GetNetworkList(&network_list, + net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES); + return network_list; +} + } // namespace WebRtcLogBuffer::WebRtcLogBuffer() @@ -197,9 +206,10 @@ if (!meta_data_) meta_data_.reset(new MetaDataMap()); - base::PostTaskWithTraits( + base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, - base::BindOnce(&WebRtcTextLogHandler::LogInitialInfoOnFileThread, this, + base::BindOnce(&GetNetworkInterfaceList), + base::BindOnce(&WebRtcTextLogHandler::LogInitialInfoOnIOThread, this, callback)); return true; } @@ -377,21 +387,9 @@ base::BindOnce(callback, success, error_message_with_state)); } -void WebRtcTextLogHandler::LogInitialInfoOnFileThread( - const GenericDoneCallback& callback) { - net::NetworkInterfaceList network_list; - net::GetNetworkList(&network_list, - net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES); - - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&WebRtcTextLogHandler::LogInitialInfoOnIOThread, this, - network_list, callback)); -} - void WebRtcTextLogHandler::LogInitialInfoOnIOThread( - const net::NetworkInterfaceList& network_list, - const GenericDoneCallback& callback) { + const GenericDoneCallback& callback, + const net::NetworkInterfaceList& network_list) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (logging_state_ != STARTING) { FireGenericDoneCallback(callback, false, "Logging cancelled.");
diff --git a/chrome/browser/media/webrtc/webrtc_text_log_handler.h b/chrome/browser/media/webrtc/webrtc_text_log_handler.h index f7ff559..6969780 100644 --- a/chrome/browser/media/webrtc/webrtc_text_log_handler.h +++ b/chrome/browser/media/webrtc/webrtc_text_log_handler.h
@@ -138,9 +138,8 @@ void LogToCircularBuffer(const std::string& message); - void LogInitialInfoOnFileThread(const GenericDoneCallback& callback); - void LogInitialInfoOnIOThread(const net::NetworkInterfaceList& network_list, - const GenericDoneCallback& callback); + void LogInitialInfoOnIOThread(const GenericDoneCallback& callback, + const net::NetworkInterfaceList& network_list); void EnableBrowserProcessLoggingOnUIThread(); void DisableBrowserProcessLoggingOnUIThread();
diff --git a/chrome/browser/resources/md_extensions/keyboard_shortcuts.html b/chrome/browser/resources/md_extensions/keyboard_shortcuts.html index 1e38e2a..077a9f2 100644 --- a/chrome/browser/resources/md_extensions/keyboard_shortcuts.html +++ b/chrome/browser/resources/md_extensions/keyboard_shortcuts.html
@@ -14,26 +14,36 @@ <template> <style include="md-select cr-shared-style"> :host { + --card-max-width: 928px; + --card-min-width: 600px; height: 100%; } + #instructions, + .shortcut-card { + margin: 0 auto 16px auto; + max-width: var(--card-max-width); + min-width: var(--card-min-width); + width: 90%; + } + + #instructions { + @apply --cr-title-text; + } + + .shortcut-card { + @apply --cr-primary-text; + @apply --shadow-elevation-2dp; + background-color: white; + padding-bottom: 8px; + } + #container { height: 100%; overflow: overlay; padding-top: 24px; } - .shortcut-card { - @apply(--cr-primary-text); - @apply(--shadow-elevation-2dp); - background-color: white; - margin: 0 auto 16px auto; - max-width: 928px; - min-width: 600px; - padding-bottom: 8px; - width: 90%; - } - .command-entry { align-items: center; display: flex; @@ -65,7 +75,7 @@ display: flex; margin-bottom: 9px; padding: 16px var(--cr-section-padding); - @apply(--cr-title-text); + @apply --cr-title-text; } .icon { @@ -82,6 +92,7 @@ } </style> <div id="container"> + <div id="instructions">$i18n{shortcutInstructions}</div> <template is="dom-repeat" items="[[calculateShownItems_(items.*)]]"> <div class="shortcut-card"> <div class="card-title">
diff --git a/chrome/browser/resources/md_extensions/shortcut_input.html b/chrome/browser/resources/md_extensions/shortcut_input.html index 4fce312..ad5c9bb 100644 --- a/chrome/browser/resources/md_extensions/shortcut_input.html +++ b/chrome/browser/resources/md_extensions/shortcut_input.html
@@ -25,7 +25,7 @@ margin-bottom: 0px; margin-top: 2px; /* Offset underline spacing. */ padding: 0; - @apply(--cr-primary-text); + @apply --cr-primary-text; }; } @@ -38,8 +38,12 @@ </style> <div id="main"> <paper-input id="input" placeholder="$i18n{shortcutTypeAShortcut}" - value="[[computeText_(capturing_, shortcut, pendingShortcut_)]]" - no-label-float> + error-message="[[getErrorString_(error_, + '$i18nPolymer{shortcutIncludeStartModifier}', + '$i18nPolymer{shortcutTooManyModifiers}', + '$i18nPolymer{shortcutNeedCharacter}')]]" + value="[[computeText_(capturing_, shortcut, pendingShortcut_)]]" + no-label-float> </paper-input> <button id="clear" is="paper-icon-button-light" class="icon-clear no-overlap" on-tap="onClearTap_"
diff --git a/chrome/browser/resources/md_extensions/shortcut_input.js b/chrome/browser/resources/md_extensions/shortcut_input.js index 6622e67..d70ebd02 100644 --- a/chrome/browser/resources/md_extensions/shortcut_input.js +++ b/chrome/browser/resources/md_extensions/shortcut_input.js
@@ -5,6 +5,14 @@ cr.define('extensions', function() { 'use strict'; + /** @enum {number} */ + const ShortcutError = { + NO_ERROR: 0, + INCLUDE_START_MODIFIER: 1, + TOO_MANY_MODIFIERS: 2, + NEED_CHARACTER: 3, + }; + // The UI to display and manage keyboard shortcuts set for extension commands. const ShortcutInput = Polymer({ is: 'extensions-shortcut-input', @@ -36,6 +44,12 @@ value: false, }, + /** @private {!ShortcutError} */ + error_: { + type: Number, + value: 0, + }, + /** @private */ pendingShortcut_: { type: String, @@ -67,7 +81,9 @@ return; this.pendingShortcut_ = ''; this.capturing_ = false; - this.$['input'].blur(); + const input = this.$.input; + input.blur(); + input.invalid = false; this.delegate.setShortcutHandlingSuspended(false); }, @@ -110,6 +126,23 @@ }, /** + * @param {!ShortcutError} error + * @param {string} includeStartModifier + * @param {string} tooManyModifiers + * @param {string} needCharacter + * @return {string} UI string. + * @private + */ + getErrorString_: function( + error, includeStartModifier, tooManyModifiers, needCharacter) { + if (error == ShortcutError.TOO_MANY_MODIFIERS) + return tooManyModifiers; + if (error == ShortcutError.NEED_CHARACTER) + return needCharacter; + return includeStartModifier; + }, + + /** * @param {!KeyboardEvent} e * @private */ @@ -123,17 +156,27 @@ // We don't allow both Ctrl and Alt in the same keybinding. // TODO(devlin): This really should go in extensions.hasValidModifiers, // but that requires updating the existing page as well. - if ((e.ctrlKey && e.altKey) || !extensions.hasValidModifiers(e)) { - this.pendingShortcut_ = 'invalid'; + if (e.ctrlKey && e.altKey) { + this.error_ = ShortcutError.TOO_MANY_MODIFIERS; + this.$.input.invalid = true; return; } - - this.pendingShortcut_ = extensions.keystrokeToString(e); - - if (extensions.isValidKeyCode(e.keyCode)) { - this.commitPending_(); - this.endCapture_(); + if (!extensions.hasValidModifiers(e)) { + this.pendingShortcut_ = ''; + this.error_ = ShortcutError.INCLUDE_START_MODIFIER; + this.$.input.invalid = true; + return; } + this.pendingShortcut_ = extensions.keystrokeToString(e); + if (!extensions.isValidKeyCode(e.keyCode)) { + this.error_ = ShortcutError.NEED_CHARACTER; + this.$.input.invalid = true; + return; + } + this.$.input.invalid = false; + + this.commitPending_(); + this.endCapture_(); }, /** @private */
diff --git a/chrome/browser/resources/net_internals/events_view.js b/chrome/browser/resources/net_internals/events_view.js index 679fdbc..60cd5a8 100644 --- a/chrome/browser/resources/net_internals/events_view.js +++ b/chrome/browser/resources/net_internals/events_view.js
@@ -144,13 +144,6 @@ }, /** - * Updates text in the details view when privacy stripping is toggled. - */ - onPrivacyStrippingChanged: function() { - this.invalidateDetailsView_(); - }, - - /** * Updates text in the details view when time display mode is toggled. */ onUseRelativeTimesChanged: function() {
diff --git a/chrome/browser/resources/net_internals/log_util.js b/chrome/browser/resources/net_internals/log_util.js index f690352a..b616f2e 100644 --- a/chrome/browser/resources/net_internals/log_util.js +++ b/chrome/browser/resources/net_internals/log_util.js
@@ -9,8 +9,7 @@ * Creates a new log dump. |events| is a list of all events, |polledData| is * an object containing the results of each poll, |tabData| is an object * containing data for individual tabs, |date| is the time the dump was - * created, as a formatted string, and |privacyStripping| is whether or not - * private information should be removed from the generated dump. + * created, as a formatted string. * * Returns the new log dump as an object. Resulting object may have a null * |numericDate|. @@ -32,11 +31,7 @@ * tabs not present on the OS the log is from. */ function createLogDump( - userComments, constants, events, polledData, tabData, numericDate, - privacyStripping) { - if (privacyStripping) - events = events.map(stripPrivacyInfo); - + userComments, constants, events, polledData, tabData, numericDate) { var logDump = { 'userComments': userComments, 'constants': constants, @@ -57,12 +52,11 @@ * Creates a full log dump using |polledData| and the return value of each * tab's saveState function and passes it to |callback|. */ - function onUpdateAllCompleted( - userComments, callback, privacyStripping, polledData) { + function onUpdateAllCompleted(userComments, callback, polledData) { var logDump = createLogDump( userComments, Constants, EventsTracker.getInstance().getAllCapturedEvents(), polledData, - getTabData_(), timeutil.getCurrentTime(), privacyStripping); + getTabData_(), timeutil.getCurrentTime()); callback(JSON.stringify(logDump)); } @@ -71,9 +65,9 @@ * loaded. Once a log dump has been created, |callback| is passed the dumped * text as a string. */ - function createLogDumpAsync(userComments, callback, privacyStripping) { - g_browser.updateAllInfo(onUpdateAllCompleted.bind( - null, userComments, callback, privacyStripping)); + function createLogDumpAsync(userComments, callback) { + g_browser.updateAllInfo( + onUpdateAllCompleted.bind(null, userComments, callback)); } /**
diff --git a/chrome/browser/resources/net_internals/log_view_painter.js b/chrome/browser/resources/net_internals/log_view_painter.js index edb063be..205fcfa 100644 --- a/chrome/browser/resources/net_internals/log_view_painter.js +++ b/chrome/browser/resources/net_internals/log_view_painter.js
@@ -6,7 +6,6 @@ var createLogEntryTablePrinter; var proxySettingsToString; -var stripPrivacyInfo; // Start of anonymous namespace. (function() { @@ -22,8 +21,7 @@ * Creates a TablePrinter for use by the above two functions. baseTime is * the time relative to which other times are displayed. */ -createLogEntryTablePrinter = function( - logEntries, privacyStripping, baseTime, logCreationTime) { +createLogEntryTablePrinter = function(logEntries, baseTime, logCreationTime) { var entries = LogGroupEntry.createArrayFrom(logEntries); var tablePrinter = new TablePrinter(); var parameterOutputter = new ParameterOutputter(tablePrinter); @@ -66,7 +64,7 @@ if (typeof entry.orig.params == 'object') { // Those 5 skipped cells are: two for "t=", and three for "st=". tablePrinter.setNewRowCellIndent(5 + entry.getDepth()); - writeParameters(entry.orig, privacyStripping, parameterOutputter); + writeParameters(entry.orig, parameterOutputter); tablePrinter.setNewRowCellIndent(0); } @@ -240,15 +238,10 @@ * Certain event types have custom pretty printers. Everything else will * default to a JSON-like format. */ -function writeParameters(entry, privacyStripping, out) { - if (privacyStripping) { - // If privacy stripping is enabled, remove data as needed. - entry = stripPrivacyInfo(entry); - } else { - // If headers are in an object, convert them to an array for better - // display. - entry = reformatHeaders(entry); - } +function writeParameters(entry, out) { + // If headers are in an object, convert them to an array for better + // display. + entry = reformatHeaders(entry); // Use any parameter writer available for this event type. var paramsWriter = getParameterWriterForEventType(entry.type); @@ -442,131 +435,6 @@ } /** - * Removes a cookie or unencrypted login information from a single HTTP header - * line, if present, and returns the modified line. Otherwise, just returns - * the original line. - * - * Note: this logic should be kept in sync with - * net::ElideHeaderValueForNetLog in net/http/http_log_util.cc. - */ -function stripCookieOrLoginInfo(line) { - var patterns = [ - // Cookie patterns - /^set-cookie: /i, /^set-cookie2: /i, /^cookie: /i, - - // Unencrypted authentication patterns - /^authorization: \S*\s*/i, /^proxy-authorization: \S*\s*/i - ]; - - // Prefix will hold the first part of the string that contains no private - // information. If null, no part of the string contains private - // information. - var prefix = null; - for (var i = 0; i < patterns.length; i++) { - var match = patterns[i].exec(line); - if (match != null) { - prefix = match[0]; - break; - } - } - - // Look for authentication information from data received from the server in - // multi-round Negotiate authentication. - if (prefix === null) { - var challengePatterns = - [/^www-authenticate: (\S*)\s*/i, /^proxy-authenticate: (\S*)\s*/i]; - for (var i = 0; i < challengePatterns.length; i++) { - var match = challengePatterns[i].exec(line); - if (!match) - continue; - - // If there's no data after the scheme name, do nothing. - if (match[0].length == line.length) - break; - - // Ignore lines with commas, as they may contain lists of schemes, and - // the information we want to hide is Base64 encoded, so has no commas. - if (line.indexOf(',') >= 0) - break; - - // Ignore Basic and Digest authentication challenges, as they contain - // public information. - if (/^basic$/i.test(match[1]) || /^digest$/i.test(match[1])) - break; - - prefix = match[0]; - break; - } - } - - if (prefix) { - var suffix = line.slice(prefix.length); - // If private information has already been removed, keep the line as-is. - // This is often the case when viewing a loaded log. - if (suffix.search(/^\[[0-9]+ bytes were stripped\]$/) == -1) { - return prefix + '[' + suffix.length + ' bytes were stripped]'; - } - } - - return line; -} - -/** - * Remove debug data from HTTP/2 GOAWAY frame due to privacy considerations, - * see - * https://httpwg.github.io/specs/rfc7540.html#GOAWAY. - * - * Note: this logic should be kept in sync with - * net::ElideGoAwayDebugDataForNetLog in net/http/http_log_util.cc. - */ -function stripGoAwayDebugData(value) { - return '[' + value.length + ' bytes were stripped]'; -} - -/** - * If |entry| has headers, returns a copy of |entry| with all cookie and - * unencrypted login text removed. Otherwise, returns original |entry| - * object. - * This is needed so that JSON log dumps can be made without affecting the - * source data. Converts headers stored in objects to arrays. - */ -stripPrivacyInfo = function(entry) { - if (!entry.params) { - return entry; - } - - if (entry.type == EventType.HTTP2_SESSION_GOAWAY && - entry.params.debug_data != undefined) { - // Duplicate the top level object, and |entry.params|. All other fields - // are - // just pointers to the original values, as they won't be modified, other - // than |entry.params.debug_data|. - entry = shallowCloneObject(entry); - entry.params = shallowCloneObject(entry.params); - entry.params.debug_data = stripGoAwayDebugData(entry.params.debug_data); - return entry; - } - - if (entry.params.headers === undefined || - !(entry.params.headers instanceof Object)) { - return entry; - } - - // Make sure entry's headers are in an array. - entry = reformatHeaders(entry); - - // Duplicate the top level object, and |entry.params|. All other fields are - // just pointers to the original values, as they won't be modified, other - // than - // |entry.params.headers|. - entry = shallowCloneObject(entry); - entry.params = shallowCloneObject(entry.params); - - entry.params.headers = entry.params.headers.map(stripCookieOrLoginInfo); - return entry; -}; - -/** * Outputs the request header parameters of |entry| to |out|. */ function writeParamsForRequestHeaders(entry, out, consumedParams) {
diff --git a/chrome/browser/resources/net_internals/main.js b/chrome/browser/resources/net_internals/main.js index 6b286ea8..ca6ce6d 100644 --- a/chrome/browser/resources/net_internals/main.js +++ b/chrome/browser/resources/net_internals/main.js
@@ -125,10 +125,8 @@ this.stopCapturing(); if (opt_fileName != undefined) { // If there's a file name, a log file was loaded, so swap out the status - // bar to indicate we're no longer capturing events. Also disable - // hiding cookies, so if the log dump has them, they'll be displayed. + // bar to indicate we're no longer capturing events. this.topBarView_.switchToSubView('loaded').setFileName(opt_fileName); - SourceTracker.getInstance().setPrivacyStripping(false); } else { // Otherwise, the "Stop Capturing" button was presumably pressed. // Don't disable hiding cookies, so created log dumps won't have them,
diff --git a/chrome/browser/resources/net_internals/source_entry.js b/chrome/browser/resources/net_internals/source_entry.js index bb1db6fc..100d72e 100644 --- a/chrome/browser/resources/net_internals/source_entry.js +++ b/chrome/browser/resources/net_internals/source_entry.js
@@ -335,7 +335,7 @@ */ createTablePrinter: function() { return createLogEntryTablePrinter( - this.entries_, SourceTracker.getInstance().getPrivacyStripping(), + this.entries_, SourceTracker.getInstance().getUseRelativeTimes() ? timeutil.getBaseTime() : 0,
diff --git a/chrome/browser/resources/net_internals/source_tracker.js b/chrome/browser/resources/net_internals/source_tracker.js index 9e870db..9dce848 100644 --- a/chrome/browser/resources/net_internals/source_tracker.js +++ b/chrome/browser/resources/net_internals/source_tracker.js
@@ -18,11 +18,6 @@ // Observers that only want to receive lists of updated SourceEntries. this.sourceEntryObservers_ = []; - // True when cookies and authentication information should be removed from - // displayed events. When true, such information should be hidden from - // all pages. - this.privacyStripping_ = true; - // True when times should be displayed as milliseconds since the first // event, as opposed to milliseconds since January 1, 1970. this.useRelativeTimes_ = true; @@ -135,26 +130,6 @@ }, /** - * Sets the value of |privacyStripping_| and informs log observers - * of the change. - */ - setPrivacyStripping: function(privacyStripping) { - this.privacyStripping_ = privacyStripping; - for (var i = 0; i < this.sourceEntryObservers_.length; ++i) { - if (this.sourceEntryObservers_[i].onPrivacyStrippingChanged) - this.sourceEntryObservers_[i].onPrivacyStrippingChanged(); - } - }, - - /** - * Returns whether or not cookies and authentication information should be - * displayed for events that contain them. - */ - getPrivacyStripping: function() { - return this.privacyStripping_; - }, - - /** * Sets the value of |useRelativeTimes_| and informs log observers * of the change. */ @@ -176,12 +151,10 @@ /** * Adds a listener of SourceEntries. |observer| will be called back when - * SourceEntries are added or modified, source entries are deleted, or - * privacy stripping changes: + * SourceEntries are added or modified or source entries are deleted. * * observer.onSourceEntriesUpdated(sourceEntries) * observer.onAllSourceEntriesDeleted() - * observer.onPrivacyStrippingChanged() */ addSourceEntryObserver: function(observer) { this.sourceEntryObservers_.push(observer);
diff --git a/chrome/browser/resources/offline_pages/offline_internals.css b/chrome/browser/resources/offline_pages/offline_internals.css index 534ae985..d8ad7a5 100644 --- a/chrome/browser/resources/offline_pages/offline_internals.css +++ b/chrome/browser/resources/offline_pages/offline_internals.css
@@ -47,6 +47,10 @@ background-color: lavender; } +dialog { + border: none; +} + #current-status { font-size: 15px; } @@ -55,3 +59,10 @@ font-family: monospace; white-space: pre-wrap; } + +#dump-box { + box-sizing: border-box; + display: block; + resize: none; + width: 100%; +}
diff --git a/chrome/browser/resources/offline_pages/offline_internals.html b/chrome/browser/resources/offline_pages/offline_internals.html index 2590edb..7ba272d 100644 --- a/chrome/browser/resources/offline_pages/offline_internals.html +++ b/chrome/browser/resources/offline_pages/offline_internals.html
@@ -19,8 +19,15 @@ <div> <span id="current-status"></span> <button id="refresh">Refresh page</button> - <button id="download">Dump</button> + <button id="dump">Dump</button> </div> + <dialog id="dump"> + <textarea id="dump-box" name="json-box" rows="10" cols="40" readonly> + </textarea> + <button id="copy-to-clipboard">Copy</button> + <button id="close-dump">Close</button> + <span id="dump-info"></span> + </dialog> <h2>Event Logs</h2> <div>
diff --git a/chrome/browser/resources/offline_pages/offline_internals.js b/chrome/browser/resources/offline_pages/offline_internals.js index 2605b0b..65762808 100644 --- a/chrome/browser/resources/offline_pages/offline_internals.js +++ b/chrome/browser/resources/offline_pages/offline_internals.js
@@ -173,13 +173,26 @@ * Downloads all the stored page and request queue information into a file. * TODO(chili): Create a CSV writer that can abstract out the line joining. */ - function download() { + function dumpAsJson() { var json = JSON.stringify( {offlinePages: offlinePages, savePageRequests: savePageRequests}, null, 2); - window.open( - 'data:application/json,' + encodeURIComponent(json), 'dump.json'); + $('dump-box').value = json; + $('dump-info').textContent = ''; + $('dump').showModal(); + $('dump-box').select(); + } + + function closeDump() { + $('dump').close(); + $('dump-box').value = ''; + } + + function copyDump() { + $('dump-box').select(); + document.execCommand('copy'); + $('dump-info').textContent = 'Copied to clipboard!'; } /** @@ -260,22 +273,19 @@ } var incognito = loadTimeData.getBoolean('isIncognito'); - $('delete-all-pages').disabled = incognito; - $('delete-selected-pages').disabled = incognito; - $('delete-all-requests').disabled = incognito; - $('delete-selected-requests').disabled = incognito; - $('log-model-on').disabled = incognito; - $('log-model-off').disabled = incognito; - $('log-request-on').disabled = incognito; - $('log-request-off').disabled = incognito; - $('refresh').disabled = incognito; + ['delete-all-pages', 'delete-selected-pages', 'delete-all-requests', + 'delete-selected-requests', 'log-model-on', 'log-model-off', + 'log-request-on', 'log-request-off', 'refresh'] + .forEach(el => $(el).disabled = incognito); $('delete-all-pages').onclick = deleteAllPages; $('delete-selected-pages').onclick = deleteSelectedPages; $('delete-all-requests').onclick = deleteAllRequests; $('delete-selected-requests').onclick = deleteSelectedRequests; $('refresh').onclick = refreshAll; - $('download').onclick = download; + $('dump').onclick = dumpAsJson; + $('close-dump').onclick = closeDump; + $('copy-to-clipboard').onclick = copyDump; $('log-model-on').onclick = togglePageModelLog.bind(this, true); $('log-model-off').onclick = togglePageModelLog.bind(this, false); $('log-request-on').onclick = toggleRequestQueueLog.bind(this, true);
diff --git a/chrome/browser/resources/settings/device_page/stylus.html b/chrome/browser/resources/settings/device_page/stylus.html index 4c50c212..ac5e133 100644 --- a/chrome/browser/resources/settings/device_page/stylus.html +++ b/chrome/browser/resources/settings/device_page/stylus.html
@@ -29,13 +29,15 @@ } </style> - <settings-toggle-button class="continuation" + <settings-toggle-button id="enableStylusToolsToggle" + class="continuation" pref="{{prefs.settings.enable_stylus_tools}}" label="$i18n{stylusEnableStylusTools}"> </settings-toggle-button> <template is="dom-if" if="[[hasInternalStylus_]]"> <settings-toggle-button + id ="launchPaletteOnEjectEventToggle" pref="{{prefs.settings.launch_palette_on_eject_event}}" label="$i18n{stylusAutoOpenStylusTools}" disabled="[[!prefs.settings.enable_stylus_tools.value]]">
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/OWNERS b/chrome/browser/safe_browsing/chrome_cleaner/OWNERS index 51897aa..e54e7edd 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/OWNERS +++ b/chrome/browser/safe_browsing/chrome_cleaner/OWNERS
@@ -1,4 +1,5 @@ csharp@chromium.org +joenotcharles@chromium.org robertshield@chromium.org # COMPONENT: UI>Browser>Preferences>Protector
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc index 83d9170e..4d18784 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc
@@ -160,12 +160,11 @@ // committed navigation. if (navigation_handle->IsRendererInitiated() && current_frame_host && current_frame_host->GetLastCommittedURL().is_valid()) { - nav_event->source_url = - SafeBrowsingNavigationObserverManager::ClearEmptyRef( - current_frame_host->GetLastCommittedURL()); + nav_event->source_url = SafeBrowsingNavigationObserverManager::ClearURLRef( + current_frame_host->GetLastCommittedURL()); } nav_event->original_request_url = - SafeBrowsingNavigationObserverManager::ClearEmptyRef( + SafeBrowsingNavigationObserverManager::ClearURLRef( navigation_handle->GetURL()); nav_event->source_tab_id = @@ -175,7 +174,7 @@ nav_event->source_main_frame_url = nav_event->source_url; } else { nav_event->source_main_frame_url = - SafeBrowsingNavigationObserverManager::ClearEmptyRef( + SafeBrowsingNavigationObserverManager::ClearURLRef( navigation_handle->GetWebContents()->GetLastCommittedURL()); } navigation_handle_map_[navigation_handle] = std::move(nav_event); @@ -190,7 +189,7 @@ } NavigationEvent* nav_event = navigation_handle_map_[navigation_handle].get(); nav_event->server_redirect_urls.push_back( - SafeBrowsingNavigationObserverManager::ClearEmptyRef( + SafeBrowsingNavigationObserverManager::ClearURLRef( navigation_handle->GetURL())); nav_event->last_updated = base::Time::Now(); }
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc index 5342323..876a2a3 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc
@@ -75,6 +75,9 @@ const char kLandingReferrerURL[] = "/safe_browsing/download_protection/navigation_observer/" "landing_referrer.html"; +const char kLandingReferrerURLWithQuery[] = + "/safe_browsing/download_protection/navigation_observer/" + "landing_referrer.html?bar=foo"; const char kPageBeforeLandingReferrerURL[] = "/safe_browsing/download_protection/navigation_observer/" "page_before_landing_referrer.html"; @@ -385,6 +388,14 @@ } } + void IdentifyReferrerChainForWebContents(content::WebContents* web_contents, + ReferrerChain* referrer_chain) { + observer_manager_->IdentifyReferrerChainByWebContents( + web_contents, + 2, // kDownloadAttributionUserGestureLimit + referrer_chain); + } + // Identify referrer chain of a PPAPI download and populate |referrer_chain|. void IdentifyReferrerChainForPPAPIDownload( const GURL& initiating_frame_url, @@ -2024,6 +2035,56 @@ referrer_chain.Get(0)); } +// Verify referrer chain when there are URL fragments. +IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, + DownloadAttributionWithURLFragment) { + GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL); + // Clicks on link and navigates to ".../page_before_landing_referrer.html". + ClickTestLink("attribution_should_ignore_url_fragments", 1, initial_url); + GURL expected_page_before_landing_referrer_url = + embedded_test_server()->GetURL(kPageBeforeLandingReferrerURL); + // Clicks on link and navigates to ".../landing_referrer.html?bar=foo#baz". + ClickTestLink("link_to_landing_referrer_with_query_and_fragment", 1, + expected_page_before_landing_referrer_url); + GURL expected_landing_referrer_url_with_query = + embedded_test_server()->GetURL(kLandingReferrerURLWithQuery); + // Clicks on link and navigates to ".../landing.html#". + ClickTestLink("link_to_landing_with_empty_fragment", 1, + expected_landing_referrer_url_with_query); + GURL expected_landing_url = embedded_test_server()->GetURL(kLandingURL); + + std::string test_server_ip(embedded_test_server()->host_port_pair().host()); + auto* nav_list = navigation_event_list(); + ASSERT_EQ(4U, nav_list->Size()); + + ReferrerChain referrer_chain; + SimulateUserGesture(); + IdentifyReferrerChainForWebContents( + browser()->tab_strip_model()->GetActiveWebContents(), &referrer_chain); + ASSERT_EQ(2, referrer_chain.size()); + + // Verify url fragment is cleared in referrer chain. + VerifyReferrerChainEntry(expected_landing_url, // url + GURL(), // main_frame_url + ReferrerChainEntry::LANDING_PAGE, // type + test_server_ip, // ip_address + expected_landing_referrer_url_with_query, + GURL(), // referrer_main_frame_url + false, // is_retargeting + std::vector<GURL>(), // server redirects + referrer_chain.Get(0)); + VerifyReferrerChainEntry( + expected_landing_referrer_url_with_query, // url + GURL(), // main_frame_url + ReferrerChainEntry::LANDING_REFERRER, // type + test_server_ip, // ip_address + GURL(), // referrer_url is empty since this beyonds 2 clicks. + GURL(), // referrer_main_frame_url is empty for the same reason. + false, // is_retargeting + std::vector<GURL>(), // server redirects + referrer_chain.Get(1)); +} + IN_PROC_BROWSER_TEST_F(SBNavigationObserverBrowserTest, VerifySanitizeReferrerChain) { GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc index dbbbcd4..c4b717a1 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.cc
@@ -175,7 +175,7 @@ void NavigationEventList::RecordNavigationEvent( std::unique_ptr<NavigationEvent> nav_event) { - // Skip page refresh. + // Skip page refresh and in-page navigation. if (nav_event->source_url == nav_event->GetDestinationUrl() && nav_event->source_tab_id == nav_event->target_tab_id) return; @@ -206,8 +206,8 @@ } // static -GURL SafeBrowsingNavigationObserverManager::ClearEmptyRef(const GURL& url) { - if (url.has_ref() && url.ref().empty()) { +GURL SafeBrowsingNavigationObserverManager::ClearURLRef(const GURL& url) { + if (url.has_ref()) { url::Replacements<char> replacements; replacements.ClearRef(); return url.ReplaceComponents(replacements); @@ -341,7 +341,7 @@ return INVALID_URL; NavigationEvent* nav_event = navigation_event_list_.FindNavigationEvent( - event_url, GURL(), event_tab_id); + ClearURLRef(event_url), GURL(), event_tab_id); if (!nav_event) { // We cannot find a single navigation event related to this event. return NAVIGATION_EVENT_NOT_FOUND; @@ -364,12 +364,13 @@ content::WebContents* web_contents, int user_gesture_count_limit, ReferrerChain* out_referrer_chain) { - if (!web_contents || !web_contents->GetLastCommittedURL().is_valid()) + GURL last_committed_url = web_contents->GetLastCommittedURL(); + if (!web_contents || !last_committed_url.is_valid()) return INVALID_URL; bool has_user_gesture = HasUserGesture(web_contents); int tab_id = SessionTabHelper::IdForTab(web_contents); return IdentifyReferrerChainByHostingPage( - web_contents->GetLastCommittedURL(), GURL(), tab_id, has_user_gesture, + ClearURLRef(last_committed_url), GURL(), tab_id, has_user_gesture, user_gesture_count_limit, out_referrer_chain); } @@ -385,7 +386,8 @@ return INVALID_URL; NavigationEvent* nav_event = navigation_event_list_.FindNavigationEvent( - initiating_frame_url, initiating_main_frame_url, tab_id); + ClearURLRef(initiating_frame_url), ClearURLRef(initiating_main_frame_url), + tab_id); if (!nav_event) { // We cannot find a single navigation event related to this hosting page. return NAVIGATION_EVENT_NOT_FOUND; @@ -434,18 +436,17 @@ // Remove the "#" at the end of URL, since it does not point to any actual // page fragment ID. GURL cleaned_target_url = - SafeBrowsingNavigationObserverManager::ClearEmptyRef(target_url); + SafeBrowsingNavigationObserverManager::ClearURLRef(target_url); std::unique_ptr<NavigationEvent> nav_event = base::MakeUnique<NavigationEvent>(); if (rfh) { - nav_event->source_url = - SafeBrowsingNavigationObserverManager::ClearEmptyRef( - rfh->GetLastCommittedURL()); + nav_event->source_url = SafeBrowsingNavigationObserverManager::ClearURLRef( + rfh->GetLastCommittedURL()); } nav_event->source_tab_id = SessionTabHelper::IdForTab(source_web_contents); nav_event->source_main_frame_url = - SafeBrowsingNavigationObserverManager::ClearEmptyRef( + SafeBrowsingNavigationObserverManager::ClearURLRef( source_web_contents->GetLastCommittedURL()); nav_event->original_request_url = cleaned_target_url; nav_event->target_tab_id = SessionTabHelper::IdForTab(target_web_contents);
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h index 55b2d85..15a6c6f 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h
@@ -111,11 +111,12 @@ // kUserGestureTTLInSecond. static bool IsUserGestureExpired(const base::Time& timestamp); - // Helper function to strip empty ref fragment from a URL. Many pages - // end up with a "#" at the end of their URLs due to navigation triggered by + // Helper function to strip ref fragment from a URL. Many pages end up with a + // fragment (e.g. http://bar.com/index.html#foo) at the end due to in-page + // navigation or a single "#" at the end due to navigation triggered by // href="#" and javascript onclick function. We don't want to have separate // entries for these cases in the maps. - static GURL ClearEmptyRef(const GURL& url); + static GURL ClearURLRef(const GURL& url); // Checks if we should enable observing navigations for safe browsing purpose. // Return true if the safe browsing safe browsing service is enabled and
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc index 13cb822..8dc7685c 100644 --- a/chrome/browser/themes/browser_theme_pack.cc +++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -180,13 +180,12 @@ // The order must match as the index is used in determining the raw id. bool InputScalesValid(const base::StringPiece& input, const std::vector<ui::ScaleFactor>& expected) { - size_t scales_size = static_cast<size_t>(input.size() / sizeof(float)); - if (scales_size != expected.size()) + if (input.size() != expected.size() * sizeof(float)) return false; - std::unique_ptr<float[]> scales(new float[scales_size]); + std::unique_ptr<float[]> scales(new float[expected.size()]); // Do a memcpy to avoid misaligned memory access. memcpy(scales.get(), input.data(), input.size()); - for (size_t index = 0; index < scales_size; ++index) { + for (size_t index = 0; index < expected.size(); ++index) { if (scales[index] != ui::GetScaleForScaleFactor(expected[index])) return false; }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 02e655cd..25186eb 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -74,8 +74,6 @@ "autofill/popup_view_common.h", "blocked_content/blocked_window_params.cc", "blocked_content/blocked_window_params.h", - "blocked_content/console_logger.cc", - "blocked_content/console_logger.h", "blocked_content/popup_blocker_tab_helper.cc", "blocked_content/popup_blocker_tab_helper.h", "blocked_content/popup_opener_tab_helper.cc",
diff --git a/chrome/browser/ui/blocked_content/console_logger.cc b/chrome/browser/ui/blocked_content/console_logger.cc deleted file mode 100644 index 4bb56a54..0000000 --- a/chrome/browser/ui/blocked_content/console_logger.cc +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/blocked_content/console_logger.h" - -#include "base/logging.h" -#include "content/public/browser/render_frame_host.h" - -ConsoleLogger::ConsoleLogger() = default; -ConsoleLogger::~ConsoleLogger() = default; - -void ConsoleLogger::LogInFrame(content::RenderFrameHost* render_frame_host, - content::ConsoleMessageLevel level, - const std::string& message) { - DCHECK(render_frame_host); - render_frame_host->AddMessageToConsole(level, message); -}
diff --git a/chrome/browser/ui/blocked_content/console_logger.h b/chrome/browser/ui/blocked_content/console_logger.h deleted file mode 100644 index 810b638..0000000 --- a/chrome/browser/ui/blocked_content/console_logger.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_BLOCKED_CONTENT_CONSOLE_LOGGER_H_ -#define CHROME_BROWSER_UI_BLOCKED_CONTENT_CONSOLE_LOGGER_H_ - -#include <string> - -#include "base/macros.h" -#include "content/public/common/console_message_level.h" - -namespace content { -class RenderFrameHost; -} - -// This simple class just forwards console logging to the associated -// RenderFrameHost, to send down to the renderer. It exists for unit tests to -// mock out, allowing unit tests to expect console messages without having to -// write a full browser test. -class ConsoleLogger { - public: - ConsoleLogger(); - virtual ~ConsoleLogger(); - - virtual void LogInFrame(content::RenderFrameHost* render_frame_host, - content::ConsoleMessageLevel level, - const std::string& message); - - private: - DISALLOW_COPY_AND_ASSIGN(ConsoleLogger); -}; - -#endif // CHROME_BROWSER_UI_BLOCKED_CONTENT_CONSOLE_LOGGER_H_
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.cc b/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.cc index f3df144..cb3b678 100644 --- a/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.cc +++ b/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.cc
@@ -14,7 +14,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/subresource_filter/chrome_subresource_filter_client.h" #include "chrome/browser/ui/blocked_content/blocked_window_params.h" -#include "chrome/browser/ui/blocked_content/console_logger.h" #include "chrome/browser/ui/blocked_content/popup_tracker.h" #include "chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.h" #include "chrome/browser/ui/browser_navigator.h" @@ -55,9 +54,7 @@ PopupBlockerTabHelper::PopupBlockerTabHelper(content::WebContents* web_contents) : content::WebContentsObserver(web_contents), safe_browsing_triggered_popup_blocker_( - SafeBrowsingTriggeredPopupBlocker::MaybeCreate( - web_contents, - base::MakeUnique<ConsoleLogger>())) {} + SafeBrowsingTriggeredPopupBlocker::MaybeCreate(web_contents)) {} PopupBlockerTabHelper::~PopupBlockerTabHelper() { }
diff --git a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc index b9171d52..ae03b91 100644 --- a/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc +++ b/chrome/browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc
@@ -567,3 +567,21 @@ EXPECT_EQ(first_url.host(), sample); EXPECT_EQ(rappor::UMA_RAPPOR_TYPE, type); } + +TEST_F(BlockTabUnderTest, LogsToConsole) { + EXPECT_TRUE(NavigateAndCommitWithoutGesture(GURL("https://first.test/"))); + SimulatePopup(); + const GURL blocked_url("https://example.test/"); + + const auto& messages = + content::RenderFrameHostTester::For(main_rfh())->GetConsoleMessages(); + + EXPECT_EQ(0u, messages.size()); + EXPECT_FALSE(NavigateAndCommitWithoutGesture(blocked_url)); + ExpectUIShown(true); + + EXPECT_EQ(1u, messages.size()); + std::string expected_message = base::StringPrintf(kBlockTabUnderFormatMessage, + blocked_url.spec().c_str()); + EXPECT_EQ(expected_message, messages.front()); +}
diff --git a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.cc b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.cc index c04ee92c..58d53904 100644 --- a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.cc +++ b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.cc
@@ -9,11 +9,11 @@ #include "base/memory/ptr_util.h" #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" -#include "chrome/browser/ui/blocked_content/console_logger.h" #include "components/safe_browsing/db/util.h" #include "components/safe_browsing/db/v4_protocol_manager_util.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/page_navigator.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/console_message_level.h" #include "third_party/WebKit/public/web/WebTriggeringEventInfo.h" @@ -47,8 +47,7 @@ // static std::unique_ptr<SafeBrowsingTriggeredPopupBlocker> SafeBrowsingTriggeredPopupBlocker::MaybeCreate( - content::WebContents* web_contents, - std::unique_ptr<ConsoleLogger> logger) { + content::WebContents* web_contents) { if (!base::FeatureList::IsEnabled(kAbusiveExperienceEnforce)) return nullptr; @@ -57,8 +56,8 @@ web_contents); if (!observer_manager) return nullptr; - return base::WrapUnique(new SafeBrowsingTriggeredPopupBlocker( - web_contents, observer_manager, std::move(logger))); + return base::WrapUnique( + new SafeBrowsingTriggeredPopupBlocker(web_contents, observer_manager)); } SafeBrowsingTriggeredPopupBlocker::~SafeBrowsingTriggeredPopupBlocker() = @@ -81,20 +80,17 @@ if (should_block) { LogAction(Action::kBlocked); current_page_data_->inc_num_popups_blocked(); - logger_->LogInFrame(web_contents()->GetMainFrame(), - content::CONSOLE_MESSAGE_LEVEL_ERROR, - kAbusiveEnforceMessage); + web_contents()->GetMainFrame()->AddMessageToConsole( + content::CONSOLE_MESSAGE_LEVEL_ERROR, kAbusiveEnforceMessage); } return should_block; } SafeBrowsingTriggeredPopupBlocker::SafeBrowsingTriggeredPopupBlocker( content::WebContents* web_contents, - subresource_filter::SubresourceFilterObserverManager* observer_manager, - std::unique_ptr<ConsoleLogger> logger) + subresource_filter::SubresourceFilterObserverManager* observer_manager) : content::WebContentsObserver(web_contents), scoped_observer_(this), - logger_(std::move(logger)), current_page_data_(base::MakeUnique<PageData>()), ignore_sublists_( base::GetFieldTrialParamByFeatureAsBool(kAbusiveExperienceEnforce, @@ -128,9 +124,8 @@ current_page_data_->set_is_triggered(true); LogAction(Action::kEnforcedSite); } else if (level == SubresourceFilterLevel::WARN) { - logger_->LogInFrame(web_contents()->GetMainFrame(), - content::CONSOLE_MESSAGE_LEVEL_WARNING, - kAbusiveWarnMessage); + web_contents()->GetMainFrame()->AddMessageToConsole( + content::CONSOLE_MESSAGE_LEVEL_WARNING, kAbusiveWarnMessage); LogAction(Action::kWarningSite); } LogAction(Action::kNavigation);
diff --git a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.h b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.h index c6f10db..cd4d4c5 100644 --- a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.h +++ b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.h
@@ -21,7 +21,6 @@ class WebContents; } // namespace content -class ConsoleLogger; extern const base::Feature kAbusiveExperienceEnforce; @@ -68,20 +67,18 @@ }; static std::unique_ptr<SafeBrowsingTriggeredPopupBlocker> MaybeCreate( - content::WebContents* web_contents, - std::unique_ptr<ConsoleLogger> logger); + content::WebContents* web_contents); ~SafeBrowsingTriggeredPopupBlocker() override; bool ShouldApplyStrongPopupBlocker( const content::OpenURLParams* open_url_params); private: - // The |web_contents|, |observer_manager|, and |logger| are expected to be + // The |web_contents| and |observer_manager| are expected to be // non-nullptr. SafeBrowsingTriggeredPopupBlocker( content::WebContents* web_contents, - subresource_filter::SubresourceFilterObserverManager* observer_manager, - std::unique_ptr<ConsoleLogger> logger); + subresource_filter::SubresourceFilterObserverManager* observer_manager); // content::WebContentsObserver: void DidFinishNavigation( @@ -128,9 +125,6 @@ level_for_next_committed_navigation_; // Should never be nullptr. - std::unique_ptr<ConsoleLogger> logger_; - - // Should never be nullptr. std::unique_ptr<PageData> current_page_data_; // Whether to ignore the threat pattern type. Useful for flexibility because
diff --git a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc index ec07e55..27f1890 100644 --- a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc +++ b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc
@@ -16,12 +16,12 @@ #include "base/test/scoped_feature_list.h" #include "chrome/browser/safe_browsing/test_safe_browsing_service.h" #include "chrome/browser/subresource_filter/chrome_subresource_filter_client.h" -#include "chrome/browser/ui/blocked_content/console_logger.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_browser_process.h" #include "components/safe_browsing/db/v4_protocol_manager_util.h" #include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h" #include "content/public/test/navigation_simulator.h" +#include "content/public/test/test_renderer_host.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/public/web/WebTriggeringEventInfo.h" #include "ui/base/page_transition_types.h" @@ -31,24 +31,6 @@ const char kNumBlockedHistogram[] = "ContentSettings.Popups.StrongBlocker.NumBlocked"; -class TestConsoleLogger : public ConsoleLogger { - public: - TestConsoleLogger() {} - ~TestConsoleLogger() override {} - - void LogInFrame(content::RenderFrameHost* render_frame_host, - content::ConsoleMessageLevel level, - const std::string& message) override { - messages_.push_back(message); - } - - const std::vector<std::string>& messages() { return messages_; } - - private: - std::vector<std::string> messages_; - DISALLOW_COPY_AND_ASSIGN(TestConsoleLogger); -}; - class SafeBrowsingTriggeredPopupBlockerTest : public ChromeRenderViewHostTestHarness { public: @@ -79,11 +61,8 @@ ChromeSubresourceFilterClient::CreateForWebContents(web_contents()); scoped_feature_list_ = DefaultFeatureList(); - - auto console_logger = base::MakeUnique<TestConsoleLogger>(); - console_logger_ = console_logger.get(); - popup_blocker_ = SafeBrowsingTriggeredPopupBlocker::MaybeCreate( - web_contents(), std::move(console_logger)); + popup_blocker_ = + SafeBrowsingTriggeredPopupBlocker::MaybeCreate(web_contents()); } void TearDown() override { @@ -140,16 +119,17 @@ MarkUrlAsAbusiveWithLevel(url, safe_browsing::SubresourceFilterLevel::WARN); } - TestConsoleLogger* console_logger() { return console_logger_; } + const std::vector<std::string>& GetMainFrameConsoleMessages() { + content::RenderFrameHostTester* rfh_tester = + content::RenderFrameHostTester::For(main_rfh()); + return rfh_tester->GetConsoleMessages(); + } private: std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_; scoped_refptr<FakeSafeBrowsingDatabaseManager> fake_safe_browsing_database_; std::unique_ptr<SafeBrowsingTriggeredPopupBlocker> popup_blocker_; - // Owned by the popup blocker. - TestConsoleLogger* console_logger_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(SafeBrowsingTriggeredPopupBlockerTest); }; @@ -185,11 +165,11 @@ const GURL url("https://example.test/"); MarkUrlAsAbusiveEnforce(url); NavigateAndCommit(url); - EXPECT_TRUE(console_logger()->messages().empty()); + EXPECT_TRUE(GetMainFrameConsoleMessages().empty()); EXPECT_TRUE(popup_blocker()->ShouldApplyStrongPopupBlocker(nullptr)); - EXPECT_EQ(1u, console_logger()->messages().size()); - EXPECT_EQ(console_logger()->messages().front(), kAbusiveEnforceMessage); + EXPECT_EQ(1u, GetMainFrameConsoleMessages().size()); + EXPECT_EQ(GetMainFrameConsoleMessages().front(), kAbusiveEnforceMessage); } TEST_F(SafeBrowsingTriggeredPopupBlockerTest, @@ -216,15 +196,15 @@ const GURL url("https://example.test/"); NavigateAndCommit(url); EXPECT_FALSE(popup_blocker()->ShouldApplyStrongPopupBlocker(nullptr)); - EXPECT_TRUE(console_logger()->messages().empty()); + EXPECT_TRUE(GetMainFrameConsoleMessages().empty()); } TEST_F(SafeBrowsingTriggeredPopupBlockerTest, NoFeature_NoCreating) { - EXPECT_NE(nullptr, SafeBrowsingTriggeredPopupBlocker::MaybeCreate( - web_contents(), base::MakeUnique<ConsoleLogger>())); + EXPECT_NE(nullptr, + SafeBrowsingTriggeredPopupBlocker::MaybeCreate(web_contents())); ResetFeatureAndGet(); - EXPECT_EQ(nullptr, SafeBrowsingTriggeredPopupBlocker::MaybeCreate( - web_contents(), base::MakeUnique<ConsoleLogger>())); + EXPECT_EQ(nullptr, + SafeBrowsingTriggeredPopupBlocker::MaybeCreate(web_contents())); } TEST_F(SafeBrowsingTriggeredPopupBlockerTest, OnlyBlockOnMatchingUrls) { @@ -368,8 +348,8 @@ NavigateAndCommit(url); // Warning should come at navigation commit time, not at popup time. - EXPECT_EQ(1u, console_logger()->messages().size()); - EXPECT_EQ(console_logger()->messages().front(), kAbusiveWarnMessage); + EXPECT_EQ(1u, GetMainFrameConsoleMessages().size()); + EXPECT_EQ(GetMainFrameConsoleMessages().front(), kAbusiveWarnMessage); EXPECT_FALSE(popup_blocker()->ShouldApplyStrongPopupBlocker(nullptr)); }
diff --git a/chrome/browser/ui/cocoa/first_run_dialog.mm b/chrome/browser/ui/cocoa/first_run_dialog.mm index 3696d85..ca7732aa4 100644 --- a/chrome/browser/ui/cocoa/first_run_dialog.mm +++ b/chrome/browser/ui/cocoa/first_run_dialog.mm
@@ -4,6 +4,7 @@ #import "chrome/browser/ui/cocoa/first_run_dialog.h" +#include "base/command_line.h" #include "base/compiler_specific.h" #include "base/mac/bundle_locations.h" #import "base/mac/scoped_nsobject.h" @@ -19,6 +20,7 @@ #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/shell_integration.h" #include "chrome/browser/ui/cocoa/first_run_dialog_controller.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" #include "components/search_engines/template_url_service.h" #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h" @@ -94,17 +96,23 @@ return !first_run::IsMetricsReportingOptIn(); } +bool IsFirstRunEnabledForBuildType() { +#if defined(GOOGLE_CHROME_BUILD) + return true; +#else + return base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kForceUnofficialFirstRun); +#endif +} + } // namespace namespace first_run { bool ShowFirstRunDialog(Profile* profile) { bool dialog_shown = false; -#if defined(GOOGLE_CHROME_BUILD) - dialog_shown = ShowFirstRunModal(profile); -#else - (void)ShowFirstRunModal; // Placate compiler. -#endif + if (IsFirstRunEnabledForBuildType()) + dialog_shown = ShowFirstRunModal(profile); // Set preference to show first run bubble and welcome page. // Only display the bubble if there is a default search provider. TemplateURLService* search_engines_model =
diff --git a/chrome/browser/ui/cocoa/first_run_dialog_controller.mm b/chrome/browser/ui/cocoa/first_run_dialog_controller.mm index d95f601..0226e41 100644 --- a/chrome/browser/ui/cocoa/first_run_dialog_controller.mm +++ b/chrome/browser/ui/cocoa/first_run_dialog_controller.mm
@@ -23,10 +23,10 @@ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); } -void MoveViewsDown(NSArray* views, CGFloat distance) { +void MoveViewsVertically(NSArray* views, CGFloat distance) { for (NSView* view : views) { NSRect frame = view.frame; - frame.origin.y -= distance; + frame.origin.y += distance; [view setFrame:frame]; } } @@ -124,18 +124,35 @@ [self.view addSubview:bottomSeparator]; [self.view addSubview:startChromeButton]; - // Now that the content view is constructed, fix the layout: since this view - // isn't using autolayout, if the widths of some of the subviews change - // because of localization, they need to be resized and perhaps repositioned, - // which is done here by |VerticallyReflowGroup()|. - CGFloat oldWidth = NSWidth([startChromeButton frame]); - cocoa_l10n_util::VerticallyReflowGroup( - @[ defaultBrowserCheckbox_, statsCheckbox_ ]); + // Now that the content view is constructed, fix the layout. The first step is + // to reflow the browser and stats checkbox texts, which can be quite lengthy + // in some locales. They may wrap onto additional lines, and in doing so cause + // the rest of the dialog to need to be rearranged. + { + CGFloat delta = cocoa_l10n_util::VerticallyReflowGroup( + @[ defaultBrowserCheckbox_, statsCheckbox_ ]); + if (delta) { + // If reflowing the checkboxes produced a height delta, move the + // checkboxes and the items above them in the content view upward, then + // grow the content view to match. This has the effect of moving + // everything visually-below the checkboxes downwards and expanding the + // window, leaving the vertical space the checkboxes need for their text. + MoveViewsVertically( + @[ defaultBrowserCheckbox_, statsCheckbox_, topSeparator, topBox ], + delta); + NSRect frame = [self.view frame]; + frame.size.height += delta; + [self.view setAutoresizesSubviews:NO]; + [self.view setFrame:frame]; + [self.view setAutoresizesSubviews:YES]; + } + } // The "Start Chrome" button needs to be sized to fit the localized string // inside it, but it should still be at the right-most edge of the dialog, so // any width added or subtracted by |sizeToFit| is added to its x coord, which // keeps its right edge where it was. + CGFloat oldWidth = NSWidth([startChromeButton frame]); [startChromeButton sizeToFit]; NSRect frame = [startChromeButton frame]; frame.origin.x += oldWidth - NSWidth([startChromeButton frame]); @@ -146,7 +163,7 @@ // view, and resize the content view itself so there isn't extra space. if (!defaultBrowserCheckboxVisible_) { CGFloat delta = NSHeight([defaultBrowserCheckbox_ frame]); - MoveViewsDown(@[ topBox, topSeparator ], delta); + MoveViewsVertically(@[ topBox, topSeparator ], -delta); NSRect frame = [self.view frame]; frame.size.height -= delta; [self.view setAutoresizesSubviews:NO];
diff --git a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc index 332d7d5..9e48fe1 100644 --- a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc
@@ -9,6 +9,7 @@ #include "ash/public/cpp/window_properties.h" #include "ash/public/cpp/window_state_type.h" #include "ash/public/interfaces/window_pin_type.mojom.h" +#include "ash/public/interfaces/window_properties.mojom.h" #include "ash/public/interfaces/window_state_type.mojom.h" #include "ash/root_window_controller.h" #include "ash/shell.h" @@ -79,6 +80,10 @@ converter->RegisterPrimitiveProperty( ash::kWindowPinTypeKey, ash::mojom::kWindowPinType_Property, base::Bind(&ash::IsValidWindowPinType)); + converter->RegisterPrimitiveProperty( + ash::kWindowPositionManagedTypeKey, + ash::mojom::kWindowPositionManaged_Property, + aura::PropertyConverter::CreateAcceptAnyValueCallback()); converter->RegisterStringProperty( ash::kShelfIDKey, ui::mojom::WindowManager::kShelfID_Property);
diff --git a/chrome/browser/ui/views/frame/browser_frame_ash.cc b/chrome/browser/ui/views/frame/browser_frame_ash.cc index cd39767..61ff458 100644 --- a/chrome/browser/ui/views/frame/browser_frame_ash.cc +++ b/chrome/browser/ui/views/frame/browser_frame_ash.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "ash/public/cpp/window_properties.h" #include "ash/shell.h" #include "ash/wm/window_properties.h" #include "ash/wm/window_state.h" @@ -153,8 +154,6 @@ void BrowserFrameAsh::SetWindowAutoManaged() { // For browser window in Chrome OS, we should only enable the auto window // management logic for tabbed browser. - if (!browser_view_->browser()->is_type_popup()) { - ash::wm::GetWindowState(GetNativeWindow()) - ->set_window_position_managed(true); - } + if (!browser_view_->browser()->is_type_popup()) + GetNativeWindow()->SetProperty(ash::kWindowPositionManagedTypeKey, true); }
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc index b2b56a26..f8ca9841 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -64,6 +64,7 @@ #if defined(OS_CHROMEOS) #include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h" +#include "ash/public/cpp/window_properties.h" #include "ash/shell.h" #include "ash/wm/cursor_manager_test_api.h" #include "ash/wm/root_window_finder.h" @@ -766,7 +767,7 @@ #if defined(OS_CHROMEOS) bool IsWindowPositionManaged(aura::Window* window) { - return ash::wm::GetWindowState(window)->window_position_managed(); + return window->GetProperty(ash::kWindowPositionManagedTypeKey); } bool HasUserChangedWindowPositionOrSize(aura::Window* window) { return ash::wm::GetWindowState(window)->bounds_changed_by_user();
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc index 1a097d14..7a12078 100644 --- a/chrome/browser/ui/webui/extensions/extensions_ui.cc +++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/webui/extensions/extensions_ui.h" #include <memory> +#include <utility> #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" @@ -257,6 +258,14 @@ IDS_MD_EXTENSIONS_SHORTCUT_SCOPE_IN_CHROME); source->AddLocalizedString("shortcutTypeAShortcut", IDS_MD_EXTENSIONS_TYPE_A_SHORTCUT); + source->AddLocalizedString("shortcutInstructions", + IDS_MD_EXTENSIONS_SHORTCUT_INSTRUCTIONS); + source->AddLocalizedString("shortcutIncludeStartModifier", + IDS_MD_EXTENSIONS_INCLUDE_START_MODIFIER); + source->AddLocalizedString("shortcutTooManyModifiers", + IDS_MD_EXTENSIONS_TOO_MANY_MODIFIERS); + source->AddLocalizedString("shortcutNeedCharacter", + IDS_MD_EXTENSIONS_NEED_CHARACTER); source->AddString( "suspiciousInstallHelpUrl", base::ASCIIToUTF16(google_util::AppendGoogleLocaleParam(
diff --git a/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc b/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc index 3a3df7b..c8dc9dd 100644 --- a/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc +++ b/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ash/public/cpp/window_properties.h" #include "ash/scoped_root_window_for_new_windows.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/wm/window_positioner.h" #include "ash/wm/window_resizer.h" -#include "ash/wm/window_state.h" #include "base/memory/ptr_util.h" #include "chrome/browser/ui/ash/ash_util.h" #include "chrome/browser/ui/browser.h" @@ -39,8 +39,8 @@ chrome::CreateBrowserWithAuraTestWindowForParams(base::WrapUnique(window), params); if (!browser->is_type_popup()) { - ash::wm::GetWindowState(browser->window()->GetNativeWindow()) - ->set_window_position_managed(true); + browser->window()->GetNativeWindow()->SetProperty( + ash::kWindowPositionManagedTypeKey, true); } return browser; }
diff --git a/chrome/browser/vr/model/model.h b/chrome/browser/vr/model/model.h index 07df52e6de..90fd6a2 100644 --- a/chrome/browser/vr/model/model.h +++ b/chrome/browser/vr/model/model.h
@@ -28,6 +28,9 @@ ControllerModel controller; ReticleModel reticle; + bool experimental_features_enabled = false; + bool incognito = false; + std::vector<OmniboxSuggestion> omnibox_suggestions; };
diff --git a/chrome/browser/vr/test/ui_scene_manager_test.cc b/chrome/browser/vr/test/ui_scene_manager_test.cc index c8a341a9..ee60365 100644 --- a/chrome/browser/vr/test/ui_scene_manager_test.cc +++ b/chrome/browser/vr/test/ui_scene_manager_test.cc
@@ -85,6 +85,11 @@ return IsElementFacingCamera(element); } +void UiSceneManagerTest::SetIncognito(bool incognito) { + model_->incognito = incognito; + manager_->SetIncognito(incognito); +} + void UiSceneManagerTest::VerifyElementsVisible( const std::string& trace_context, const std::set<UiElementName>& names) const {
diff --git a/chrome/browser/vr/test/ui_scene_manager_test.h b/chrome/browser/vr/test/ui_scene_manager_test.h index b368b17b..95d2c0c4 100644 --- a/chrome/browser/vr/test/ui_scene_manager_test.h +++ b/chrome/browser/vr/test/ui_scene_manager_test.h
@@ -50,6 +50,8 @@ bool IsVisible(UiElementName name) const; + void SetIncognito(bool incognito); + // Verify that only the elements in the set are visible. void VerifyElementsVisible(const std::string& debug_name, const std::set<UiElementName>& names) const;
diff --git a/chrome/browser/vr/ui.cc b/chrome/browser/vr/ui.cc index b8e0340..524746f5 100644 --- a/chrome/browser/vr/ui.cc +++ b/chrome/browser/vr/ui.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/vr/ui_scene.h" #include "chrome/browser/vr/ui_scene_manager.h" #include "chrome/browser/vr/vr_shell_renderer.h" +#include "chrome/common/chrome_features.h" namespace vr { @@ -33,6 +34,8 @@ weak_ptr_factory_(this) { model_->started_for_autopresentation = ui_initial_state.web_vr_autopresentation_expected; + model_->experimental_features_enabled = + base::FeatureList::IsEnabled(features::kExperimentalVRFeatures); } Ui::~Ui() = default; @@ -56,6 +59,7 @@ } void Ui::SetIncognito(bool enabled) { + model_->incognito = enabled; scene_manager_->SetIncognito(enabled); }
diff --git a/chrome/browser/vr/ui_scene_manager.cc b/chrome/browser/vr/ui_scene_manager.cc index 804255f..b009b200 100644 --- a/chrome/browser/vr/ui_scene_manager.cc +++ b/chrome/browser/vr/ui_scene_manager.cc
@@ -48,7 +48,6 @@ #include "chrome/browser/vr/ui_scene_constants.h" #include "chrome/browser/vr/vector_icons/vector_icons.h" #include "chrome/browser/vr/vr_gl_util.h" -#include "chrome/common/chrome_features.h" #include "chrome/grit/generated_resources.h" #include "components/vector_icons/vector_icons.h" #include "ui/base/l10n/l10n_util.h" @@ -556,20 +555,23 @@ } void UiSceneManager::CreateVoiceSearchUiGroup(Model* model) { - std::unique_ptr<UiElement> element; - - auto voice_search_button = base::MakeUnique<Button>( + std::unique_ptr<UiElement> element = base::MakeUnique<Button>( base::Bind(&UiSceneManager::OnVoiceSearchButtonClicked, base::Unretained(this)), base::MakeUnique<VectorIconButtonTexture>(vector_icons::kMicrophoneIcon)); - voice_search_button_ = voice_search_button.get(); - element = std::move(voice_search_button); element->set_name(kVoiceSearchButton); element->set_draw_phase(kPhaseForeground); element->SetTranslate(kVoiceSearchButtonXOffset, 0.f, 0.f); element->SetSize(kCloseButtonWidth, kCloseButtonHeight); element->set_x_anchoring(XAnchoring::XRIGHT); - control_elements_.push_back(element.get()); + element->AddBinding(base::MakeUnique<Binding<bool>>( + base::Bind( + [](Model* m) { + return !m->incognito && m->experimental_features_enabled; + }, + base::Unretained(model)), + base::Bind([](UiElement* e, const bool& v) { e->SetVisible(v); }, + element.get()))); scene_->AddUiElement(kUrlBar, std::move(element)); auto speech_recognition_prompt = base::MakeUnique<UiElement>(); @@ -1003,10 +1005,6 @@ element->SetVisible(controls_visible); } - if (!base::FeatureList::IsEnabled(features::kExperimentalVRFeatures)) { - voice_search_button_->SetVisible(false); - } - // Close button is a special control element that needs to be hidden when in // WebVR, but it needs to be visible when in cct or fullscreen. close_button_->SetVisible(browsing_mode && (fullscreen_ || in_cct_));
diff --git a/chrome/browser/vr/ui_scene_manager.h b/chrome/browser/vr/ui_scene_manager.h index e6f41fd..ffb7a311 100644 --- a/chrome/browser/vr/ui_scene_manager.h +++ b/chrome/browser/vr/ui_scene_manager.h
@@ -207,7 +207,6 @@ Rect* ceiling_ = nullptr; Grid* floor_ = nullptr; UiElement* close_button_ = nullptr; - UiElement* voice_search_button_ = nullptr; UrlBar* url_bar_ = nullptr; TransientElement* webvr_url_toast_transient_parent_ = nullptr; WebVrUrlToast* webvr_url_toast_ = nullptr;
diff --git a/chrome/browser/vr/ui_scene_manager_unittest.cc b/chrome/browser/vr/ui_scene_manager_unittest.cc index 269821d9..71ba2d9 100644 --- a/chrome/browser/vr/ui_scene_manager_unittest.cc +++ b/chrome/browser/vr/ui_scene_manager_unittest.cc
@@ -196,7 +196,7 @@ GetBackgroundColor(&fullscreen_background); EXPECT_NE(initial_background, fullscreen_background); - manager_->SetIncognito(true); + SetIncognito(true); // Make sure background has changed for incognito. SkColor incognito_background = SK_ColorBLACK; @@ -204,7 +204,7 @@ EXPECT_NE(fullscreen_background, incognito_background); EXPECT_NE(initial_background, incognito_background); - manager_->SetIncognito(false); + SetIncognito(false); SkColor no_longer_incognito_background = SK_ColorBLACK; GetBackgroundColor(&no_longer_incognito_background); EXPECT_EQ(fullscreen_background, no_longer_incognito_background); @@ -214,17 +214,40 @@ GetBackgroundColor(&no_longer_fullscreen_background); EXPECT_EQ(initial_background, no_longer_fullscreen_background); - manager_->SetIncognito(true); + SetIncognito(true); SkColor incognito_again_background = SK_ColorBLACK; GetBackgroundColor(&incognito_again_background); EXPECT_EQ(incognito_background, incognito_again_background); - manager_->SetIncognito(false); + SetIncognito(false); SkColor no_longer_incognito_again_background = SK_ColorBLACK; GetBackgroundColor(&no_longer_incognito_again_background); EXPECT_EQ(initial_background, no_longer_incognito_again_background); } +TEST_F(UiSceneManagerTest, VoiceSearchHiddenInIncognito) { + MakeManager(kNotInCct, kNotInWebVr); + + model_->experimental_features_enabled = true; + EXPECT_TRUE(OnBeginFrame()); + EXPECT_TRUE(IsVisible(kVoiceSearchButton)); + + SetIncognito(true); + EXPECT_TRUE(OnBeginFrame()); + EXPECT_FALSE(IsVisible(kVoiceSearchButton)); + + // If experimental VR features are disabled, then we should never show the + // button, regardless of whether or not we're in incognito mode. + model_->experimental_features_enabled = false; + SetIncognito(false); + EXPECT_TRUE(OnBeginFrame()); + EXPECT_FALSE(IsVisible(kVoiceSearchButton)); + + SetIncognito(true); + EXPECT_TRUE(OnBeginFrame()); + EXPECT_FALSE(IsVisible(kVoiceSearchButton)); +} + TEST_F(UiSceneManagerTest, WebVrAutopresented) { MakeAutoPresentedManager();
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 4d677aea..1f2efbe 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -899,6 +899,10 @@ // Enables Translate experimental new UX which replaces the infobar. const char kEnableTranslateNewUX[] = "enable-translate-new-ux"; +// Forces the first-run flow even on unofficial builds. Note that this still +// requires a fresh user-data-dir. +const char kForceUnofficialFirstRun[] = "force-unofficial-first-run"; + // Shows a notification when quitting Chrome with hosted apps running. Default // behavior is to also quit all hosted apps. const char kHostedAppQuitNotification[] = "enable-hosted-app-quit-notification";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index a2149a4..a8cbb0f 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -273,6 +273,7 @@ extern const char kEnableMacViewsNativeAppWindows[]; extern const char kEnableTranslateNewUX[]; extern const char kEnableUserMetrics[]; +extern const char kForceUnofficialFirstRun[]; extern const char kHostedAppQuitNotification[]; extern const char kMetricsClientID[]; extern const char kRelauncherProcess[];
diff --git a/chrome/test/data/safe_browsing/download_protection/navigation_observer/landing_referrer.html b/chrome/test/data/safe_browsing/download_protection/navigation_observer/landing_referrer.html index d7f29275..494c885 100644 --- a/chrome/test/data/safe_browsing/download_protection/navigation_observer/landing_referrer.html +++ b/chrome/test/data/safe_browsing/download_protection/navigation_observer/landing_referrer.html
@@ -13,5 +13,8 @@ <a id="link_to_landing" href="landing.html"> Link to landing </a><br> + <a id="link_to_landing_with_empty_fragment" href="landing.html#"> + Link to landing with empty fragment + </a><br> </body> </html>
diff --git a/chrome/test/data/safe_browsing/download_protection/navigation_observer/navigation_observer_tests.html b/chrome/test/data/safe_browsing/download_protection/navigation_observer/navigation_observer_tests.html index d8131247..6dcc73c 100644 --- a/chrome/test/data/safe_browsing/download_protection/navigation_observer/navigation_observer_tests.html +++ b/chrome/test/data/safe_browsing/download_protection/navigation_observer/navigation_observer_tests.html
@@ -145,5 +145,9 @@ Download via HTML5 file system API without trigger navigation </button><br> + <a id="attribution_should_ignore_url_fragments" href="page_before_landing_referrer.html"> + Attribution should ignore url fragments. + </a><br> + </body> </html>
diff --git a/chrome/test/data/safe_browsing/download_protection/navigation_observer/page_before_landing_referrer.html b/chrome/test/data/safe_browsing/download_protection/navigation_observer/page_before_landing_referrer.html index 1c898f7..f52f5a0 100644 --- a/chrome/test/data/safe_browsing/download_protection/navigation_observer/page_before_landing_referrer.html +++ b/chrome/test/data/safe_browsing/download_protection/navigation_observer/page_before_landing_referrer.html
@@ -15,5 +15,8 @@ <a id="link_to_landing_referrer" href="landing_referrer.html"> Link to landing referrer </a><br> + <a id="link_to_landing_referrer_with_query_and_fragment" href="landing_referrer.html?bar=foo#baz"> + Link to landing referrer with query and fragment + </a><br> </body> </html>
diff --git a/chrome/test/data/webui/extensions/extension_shortcut_input_test.js b/chrome/test/data/webui/extensions/extension_shortcut_input_test.js index 4a86e28..e360b114 100644 --- a/chrome/test/data/webui/extensions/extension_shortcut_input_test.js +++ b/chrome/test/data/webui/extensions/extension_shortcut_input_test.js
@@ -26,7 +26,7 @@ } /** @enum {string} */ - var TestNames = { + const TestNames = { Basic: 'basic', }; @@ -44,12 +44,9 @@ }); test(assert(TestNames.Basic), function() { - var field = input.$['input']; - var fieldText = function() { - return field.value; - }; - expectEquals('', fieldText()); - var isClearVisible = + const field = input.$['input']; + expectEquals('', field.value); + const isClearVisible = extension_test_util.isVisible.bind(null, input, '#clear', false); expectFalse(isClearVisible()); @@ -60,24 +57,36 @@ assertTrue(arg); input.delegate.reset(); - expectEquals('', fieldText()); + expectEquals('', field.value); expectFalse(isClearVisible()); + // Press character. + MockInteractions.keyDownOn(field, 'A', []); + expectEquals('', field.value); + expectTrue(field.errorMessage.startsWith('Include')); + // Add shift to character. + MockInteractions.keyDownOn(field, 'A', ['shift']); + expectEquals('', field.value); + expectTrue(field.errorMessage.startsWith('Include')); // Press ctrl. MockInteractions.keyDownOn(field, 17, ['ctrl']); - expectEquals('Ctrl', fieldText()); + expectEquals('Ctrl', field.value); + expectEquals('Need a character', field.errorMessage); // Add shift. MockInteractions.keyDownOn(field, 16, ['ctrl', 'shift']); - expectEquals('Ctrl + Shift', fieldText()); + expectEquals('Ctrl + Shift', field.value); + expectEquals('Need a character', field.errorMessage); // Remove shift. MockInteractions.keyUpOn(field, 16, ['ctrl']); - expectEquals('Ctrl', fieldText()); + expectEquals('Ctrl', field.value); + expectEquals('Need a character', field.errorMessage); // Add alt (ctrl + alt is invalid). MockInteractions.keyDownOn(field, 18, ['ctrl', 'alt']); - expectEquals('invalid', fieldText()); + expectEquals('Ctrl', field.value); // Remove alt. MockInteractions.keyUpOn(field, 18, ['ctrl']); - expectEquals('Ctrl', fieldText()); + expectEquals('Ctrl', field.value); + expectEquals('Need a character', field.errorMessage); // Add 'A'. Once a valid shortcut is typed (like Ctrl + A), it is // committed. @@ -87,7 +96,7 @@ .then((arg) => { input.delegate.reset(); expectDeepEquals(['itemid', 'Command', 'Ctrl+A'], arg); - expectEquals('Ctrl + A', fieldText()); + expectEquals('Ctrl + A', field.value); expectEquals('Ctrl+A', input.shortcut); expectTrue(isClearVisible());
diff --git a/chrome/test/data/webui/net_internals/log_util.js b/chrome/test/data/webui/net_internals/log_util.js index 867aaae..46e36b3f 100644 --- a/chrome/test/data/webui/net_internals/log_util.js +++ b/chrome/test/data/webui/net_internals/log_util.js
@@ -34,8 +34,6 @@ * Starts creating the log dump. */ start: function() { - this.initialPrivacyStripping_ = - SourceTracker.getInstance().getPrivacyStripping(); log_util.createLogDumpAsync(this.userComments_, this.onLogDumpCreated.bind(this), true); }, @@ -46,10 +44,7 @@ * @param {string} logDumpText Log dump, as a string. */ onLogDumpCreated: function(logDumpText) { - expectEquals(this.initialPrivacyStripping_, - SourceTracker.getInstance().getPrivacyStripping()); expectEquals('Log loaded.', log_util.loadLogFile(logDumpText, 'log.txt')); - expectFalse(SourceTracker.getInstance().getPrivacyStripping()); NetInternalsTest.expectStatusViewNodeVisible(LoadedStatusView.MAIN_BOX_ID); @@ -123,7 +118,6 @@ */ onLogReceived_: function(logDumpText) { assertEquals('string', typeof logDumpText); - expectTrue(SourceTracker.getInstance().getPrivacyStripping()); var expectedResult = 'Log loaded.'; @@ -134,7 +128,6 @@ logDumpText = logDumpText.substring(0, logDumpText.length - this.truncate_); expectEquals(expectedResult, log_util.loadLogFile(logDumpText, 'log.txt')); - expectFalse(SourceTracker.getInstance().getPrivacyStripping()); NetInternalsTest.expectStatusViewNodeVisible(LoadedStatusView.MAIN_BOX_ID); @@ -201,11 +194,6 @@ NetInternalsTest.checkTabLinkVisibility(tabVisibilityState, false); } -function checkPrivacyStripping(expectedValue) { - expectEquals(expectedValue, - SourceTracker.getInstance().getPrivacyStripping()); -} - /** * Checks the currently active view. * @param {string} id ID of the view that should be active. @@ -222,7 +210,6 @@ */ TEST_F('NetInternalsTest', 'netInternalsLogUtilExportImport', function() { expectFalse(g_browser.isDisabled()); - expectTrue(SourceTracker.getInstance().getPrivacyStripping()); NetInternalsTest.expectStatusViewNodeVisible(CaptureStatusView.MAIN_BOX_ID); var taskQueue = new NetInternalsTest.TaskQueue(true); @@ -269,7 +256,6 @@ NetInternalsTest.expectStatusViewNodeVisible.bind( null, HaltedStatusView.MAIN_BOX_ID)); taskQueue.addFunctionTask(checkViewsAfterLogLoaded); - taskQueue.addFunctionTask(checkPrivacyStripping.bind(null, true)); taskQueue.addFunctionTask(checkActiveView.bind(null, EventsView.TAB_ID)); taskQueue.run();
diff --git a/chrome/test/data/webui/net_internals/log_view_painter.js b/chrome/test/data/webui/net_internals/log_view_painter.js index 85812af..e93916c 100644 --- a/chrome/test/data/webui/net_internals/log_view_painter.js +++ b/chrome/test/data/webui/net_internals/log_view_painter.js
@@ -7,148 +7,6 @@ // Anonymous namespace (function() { - -/** - * Check that stripPrivacyInfo correctly removes cookies and login information. - */ -TEST_F('NetInternalsTest', 'netInternalsLogViewPainterStripInfo', function() { - // Each entry in |expectations| is a list consisting of a header element - // before and after applying the filter. If the second entry is null, the - // element should be unmodified. - var expectations = [ - ['set-cookie: blah', 'set-cookie: [4 bytes were stripped]'], - ['set-cookie2: blah', 'set-cookie2: [4 bytes were stripped]'], - ['cookie: blah', 'cookie: [4 bytes were stripped]'], - ['authorization: NTLM blah', 'authorization: NTLM [4 bytes were stripped]'], - - ['proxy-authorization: Basic blah', - 'proxy-authorization: Basic [4 bytes were stripped]'], - - ['WWW-Authenticate: Basic realm="Something, or another"', null], - - ['WWW-Authenticate: Negotiate blah-token-blah', - 'WWW-Authenticate: Negotiate [15 bytes were stripped]'], - - ['WWW-Authenticate: NTLM asdllk2j3l423lk4j23l4kj', - 'WWW-Authenticate: NTLM [23 bytes were stripped]'], - - ['WWW-Authenticate: Kerberos , Negotiate asdfasdfasdfasfa', null], - ['WWW-Authenticate: Kerberos, Negotiate asdfasdfasdfasfa', null], - ['WWW-Authenticate: Digest , Negotiate asdfasdfasdfasfa', null], - ['WWW-Authenticate: Digest realm="Foo realm", Negotiate asdf', null], - ['WWW-Authenticate: Kerberos,Digest,Basic', null], - ['WWW-Authenticate: Digest realm="asdfasdf", nonce=5, qop="auth"', null], - ['WWW-Authenticate: Basic realm=foo,foo=bar , Digest ', null], - ['Proxy-Authenticate: Basic realm="Something, or another"', null], - - ['Proxy-Authenticate: Negotiate blah-token-blah', - 'Proxy-Authenticate: Negotiate [15 bytes were stripped]'], - - ['Proxy-Authenticate: NTLM asdllk2j3l423lk4j23l4kj', - 'Proxy-Authenticate: NTLM [23 bytes were stripped]'], - - ['Proxy-Authenticate: Kerberos , Negotiate asdfasdfa', null], - ['Proxy-Authenticate: Kerberos, Negotiate asdfasdfa', null], - ['Proxy-Authenticate: Digest , Negotiate asdfasdfa', null], - ['Proxy-Authenticate: Digest realm="Foo realm", Negotiate asdfasdfa', null], - ['Proxy-Authenticate: Kerberos,Digest,Basic', null], - ['Proxy-Authenticate: Digest realm="asdfasdf", nonce=5, qop="auth"', null], - ['Proxy-Authenticate: Basic realm=foo,foo=bar , Digest ', null], - - ['cookie: [4 bytes were stripped]', null], - ['cookie: Stuff [4 bytes were stripped]', - 'cookie: [29 bytes were stripped]'], - ['cookie: [4 bytes were stripped] Stuff', - 'cookie: [29 bytes were stripped]'], - ['set-cookie: [4 bytes were stripped]', null], - ['Proxy-Authenticate: NTLM [23 bytes were stripped]', null], - ]; - - for (var i = 0; i < expectations.length; ++i) { - var expectation = expectations[i]; - // Position within params.headers where the authentication information goes. - for (var position = 0; position < 3; ++position) { - var entry = { - 'params': { - 'headers': [ - 'Host: clients1.google.com', - 'Connection: keep-alive', - 'User-Agent: Mozilla/5.0' - ], - 'line': 'GET / HTTP/1.1\r\n' - }, - 'phase': EventPhase.PHASE_BEGIN, - 'source': {'id': 329, 'type': EventSourceType.URL_REQUEST}, - 'time': '22468349', - 'type': EventSourceType.URL_REQUEST - }; - - entry.params.headers[position] = expectation[0]; - var stripped = stripPrivacyInfo(entry); - // The entry should be duplicated, so the original still has the deleted - // information. - expectNotEquals(stripped, entry); - if (expectation[1] == null) { - expectEquals(expectation[0], stripped.params.headers[position]); - } else { - expectEquals(expectation[1], stripped.params.headers[position]); - } - } - } - - // Test with HTTP/2 request headers, which use an object rather than an array. - var spdyRequestHeadersEntry = { - 'params': { - 'headers': { - ':host': 'clients1.google.com', - ':method': 'GET', - ':path': '/cute/cat/pictures/', - 'cookie': 'blah' - }, - 'line': 'GET / HTTP/1.1\r\n' - }, - 'phase': EventPhase.PHASE_BEGIN, - 'source': {'id': 329, 'type': EventSourceType.URL_REQUEST}, - 'time': '22468349', - 'type': EventSourceType.HTTP_TRANSACTION_HTTP2_SEND_REQUEST_HEADERS - }; - var strippedSpdyRequestHeadersEntry = - stripPrivacyInfo(spdyRequestHeadersEntry); - expectEquals('cookie: [4 bytes were stripped]', - strippedSpdyRequestHeadersEntry.params.headers[3]); - - testDone(); -}); - -/** - * Check that stripPrivacyInfo correctly removes HTTP/2 GOAWAY frame debug data. - */ -TEST_F('NetInternalsTest', 'netInternalsLogViewPainterStripGoAway', function() { - var entry = { - 'params': { - 'active_streams': 1, - 'debug_data': 'potentially privacy sensitive information', - 'last_accepted_stream_id': 1, - 'status': 0, - 'unclaimed_streams': 0, - }, - 'phase': 0, - 'source': {'id': 404, 'type': 5}, - 'time': '49236780', - 'type': EventType.HTTP2_SESSION_GOAWAY, - }; - - var stripped = stripPrivacyInfo(entry); - - // The entry should be duplicated, so the original still has the deleted - // information. - expectNotEquals(stripped, entry); - expectEquals('[41 bytes were stripped]', - stripped.params.debug_data); - - testDone(); -}); - /** * Tests the formatting of log entries to fixed width text. */ @@ -168,7 +26,6 @@ var tablePrinter = createLogEntryTablePrinter(testCase.logEntries, - testCase.privacyStripping, baseTime, testCase.logCreationTime); tablePrinter.toText(0, div); @@ -193,12 +50,6 @@ runTestCase(painterTestCheckedCert()); runTestCase(painterTestProxyConfigOneProxyAllSchemes()); runTestCase(painterTestProxyConfigTwoProxiesAllSchemes()); - runTestCase(painterTestDontStripCookiesURLRequest()); - runTestCase(painterTestStripCookiesURLRequest()); - runTestCase(painterTestDontStripCookiesSPDYSession()); - runTestCase(painterTestStripCookiesSPDYSession()); - runTestCase(painterTestSpdyURLRequestDontStripCookies()); - runTestCase(painterTestSpdyURLRequestStripCookies()); runTestCase(painterTestExtraCustomParameter()); runTestCase(painterTestMissingCustomParameter()); runTestCase(painterTestInProgressURLRequest()); @@ -1736,252 +1587,6 @@ } /** - * Tests that cookies are NOT stripped from URLRequests when stripping is - * disabled. - */ -function painterTestDontStripCookiesURLRequest() { - var testCase = {}; - testCase.tickOffset = '1337911098139'; - - testCase.logEntries = [ - { - 'params': { - 'headers': [ - 'HTTP/1.1 301 Moved Permanently', - 'Cache-Control: private', - 'Content-Length: 23', - 'Content-Type: text/html', - 'Location: http://msdn.microsoft.com', - 'Server: Microsoft-IIS/7.5', - 'Set-Cookie: MyMagicPony', - 'P3P: CP=\"ALL\"', - 'X-Powered-By: ASP.NET', - 'X-UA-Compatible: IE=EmulateIE7', - 'Date: Tue, 05 Jun 2012 21:06:45 GMT', - 'Connection: close' - ] - }, - 'phase': EventPhase.PHASE_NONE, - 'source': { - 'id': 829, - 'type': EventSourceType.URL_REQUEST - }, - 'time': '1019307339', - 'type': EventType.HTTP_TRANSACTION_READ_RESPONSE_HEADERS - }, - { - 'params': { - 'headers': [ - 'Host: msdn.microsoft.com', - 'Connection: keep-alive', - 'User-Agent: Mozilla/5.0', - 'Accept: text/html', - 'Accept-Encoding: gzip,deflate', - 'Accept-Language: en-US,en;q=0.8', - 'Accept-Charset: ISO-8859-1', - 'Cookie: MyMagicPony' - ], - 'line': 'GET / HTTP/1.1\r\n' - }, - 'phase': EventPhase.PHASE_NONE, - 'source': { - 'id': 829, - 'type': EventSourceType.URL_REQUEST - }, - 'time': '1019307458', - 'type': EventType.HTTP_TRANSACTION_SEND_REQUEST_HEADERS - } - ]; - - testCase.expectedText = -'t=1338930405478 [st= 0] HTTP_TRANSACTION_READ_RESPONSE_HEADERS\n' + -' --> HTTP/1.1 301 Moved Permanently\n' + -' Cache-Control: private\n' + -' Content-Length: 23\n' + -' Content-Type: text/html\n' + -' Location: http://msdn.microsoft.com\n' + -' Server: Microsoft-IIS/7.5\n' + -' Set-Cookie: MyMagicPony\n' + -' P3P: CP="ALL"\n' + -' X-Powered-By: ASP.NET\n' + -' X-UA-Compatible: IE=EmulateIE7\n' + -' Date: Tue, 05 Jun 2012 21:06:45 GMT\n' + -' Connection: close\n' + -'t=1338930405597 [st=119] HTTP_TRANSACTION_SEND_REQUEST_HEADERS\n' + -' --> GET / HTTP/1.1\n' + -' Host: msdn.microsoft.com\n' + -' Connection: keep-alive\n' + -' User-Agent: Mozilla/5.0\n' + -' Accept: text/html\n' + -' Accept-Encoding: gzip,deflate\n' + -' Accept-Language: en-US,en;q=0.8\n' + -' Accept-Charset: ISO-8859-1\n' + -' Cookie: MyMagicPony'; - - return testCase; -} - -/** - * Tests that cookies are stripped from URLRequest when stripping is enabled. - */ -function painterTestStripCookiesURLRequest() { - var testCase = painterTestDontStripCookiesURLRequest(); - testCase.privacyStripping = true; - testCase.expectedText = - testCase.expectedText.replace(/MyMagicPony/g, '[11 bytes were stripped]'); - return testCase; -} - -/** - * Tests that cookies are NOT stripped from HTTP/2 sessions when stripping is - * not enabled. This test data was pieced together in order to get a "cookie" - * and "set-cookie" header. - */ -function painterTestDontStripCookiesSPDYSession() { - var testCase = {}; - testCase.tickOffset = '1337911097783'; - - testCase.logEntries = [ - { - 'params': { - 'flags': 1, - 'headers': [ - ':host: mail.google.com', - ':method: GET', - ':path: /a/google.com', - ':scheme: https', - ':version: HTTP/1.1', - 'accept: text/html', - 'accept-charset: ISO-8859-1', - 'accept-encoding: gzip,deflate', - 'accept-language: en-US,en;q=0.8', - 'cookie: MyMagicPony', - 'user-agent: Mozilla/5.0' - ], - 'stream_id': 1 - }, - 'phase': EventPhase.PHASE_NONE, - 'source': { - 'id': 153, - 'type': EventSourceType.HTTP2_SESSION - }, - 'time': '1012984638', - 'type': EventType.HTTP2_SESSION_SEND_HEADERS - }, - { - 'params': { - 'flags': 0, - 'headers': [ - ':status: 204 No Content', - ':version: HTTP/1.1', - 'date: Tue, 05 Jun 2012 19:21:30 GMT', - 'server: GSE', - 'set-cookie: MyMagicPony', - 'x-random-header: sup' - ], - 'stream_id': 5 - }, - 'phase': EventPhase.PHASE_NONE, - 'source': { - 'id': 153, - 'type': EventSourceType.HTTP2_SESSION - }, - 'time': '1012992266', - 'type': EventType.HTTP2_SESSION_RECV_HEADERS - } - ]; - - testCase.expectedText = - 't=1338924082421 [st= 0] HTTP2_SESSION_SEND_HEADERS\n' + - ' --> flags = 1\n' + - ' --> :host: mail.google.com\n' + - ' :method: GET\n' + - ' :path: /a/google.com\n' + - ' :scheme: https\n' + - ' :version: HTTP/1.1\n' + - ' accept: text/html\n' + - ' accept-charset: ISO-8859-1\n' + - ' accept-encoding: gzip,deflate\n' + - ' accept-language: en-US,en;q=0.8\n' + - ' cookie: MyMagicPony\n' + - ' user-agent: Mozilla/5.0\n' + - ' --> stream_id = 1\n' + - 't=1338924090049 [st=7628] HTTP2_SESSION_RECV_HEADERS\n' + - ' --> flags = 0\n' + - ' --> :status: 204 No Content\n' + - ' :version: HTTP/1.1\n' + - ' date: Tue, 05 Jun 2012 19:21:30 GMT\n' + - ' server: GSE\n' + - ' set-cookie: MyMagicPony\n' + - ' x-random-header: sup\n' + - ' --> stream_id = 5'; - - return testCase; -} - -/** - * Tests that cookies are stripped from HTTP/2 sessions when stripping is - * enabled. - */ -function painterTestStripCookiesSPDYSession() { - var testCase = painterTestDontStripCookiesSPDYSession(); - testCase.privacyStripping = true; - testCase.expectedText = - testCase.expectedText.replace(/MyMagicPony/g, '[11 bytes were stripped]'); - return testCase; -} - -/** - * Tests that cookies are NOT stripped from HTTP/2 URL request headers when - * stripping is not enabled. The difference from the above requests is that - * HTTP/2 URL request headers use dictionaries rather than lists. - */ -function painterTestSpdyURLRequestDontStripCookies() { - var testCase = {}; - testCase.tickOffset = '1337911098481'; - - testCase.logEntries = [ - { - 'params': { - 'headers': { - ':host': 'www.google.com', - ':method': 'GET', - ':path': '/', - ':scheme': 'https', - ':version': 'HTTP/1.1', - 'cookie': 'MyMagicPony'}, - }, - 'phase': EventPhase.PHASE_NONE, - 'source': {'id': 329, 'type': EventSourceType.URL_REQUEST}, - 'time': '954124663', - 'type': EventType.HTTP_TRANSACTION_HTTP2_SEND_REQUEST_HEADERS - } - ]; - - testCase.expectedText = -'t=1338865223144 [st=0] HTTP_TRANSACTION_HTTP2_SEND_REQUEST_HEADERS\n' + -' --> :host: www.google.com\n' + -' :method: GET\n' + -' :path: /\n' + -' :scheme: https\n' + -' :version: HTTP/1.1\n' + -' cookie: MyMagicPony'; - return testCase; -} - -/** - * Tests that cookies are NOT stripped from HTTP/2 URL request headers when - * stripping is not enabled. The difference from the above requests is that - */ -function painterTestSpdyURLRequestStripCookies() { - var testCase = painterTestSpdyURLRequestDontStripCookies(); - testCase.privacyStripping = true; - testCase.expectedText = - testCase.expectedText.replace(/MyMagicPony/g, '[11 bytes were stripped]'); - return testCase; -} - -/** * Tests that when there are more custom parameters than we expect for an * event type, they are printed out in addition to the custom formatting. */
diff --git a/chrome/test/data/webui/settings/device_page_tests.js b/chrome/test/data/webui/settings/device_page_tests.js index add50ce..9d58b57 100644 --- a/chrome/test/data/webui/settings/device_page_tests.js +++ b/chrome/test/data/webui/settings/device_page_tests.js
@@ -247,6 +247,16 @@ value: false, }, }, + enable_stylus_tools: { + key: 'settings.enable_stylus_tools', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, + launch_palette_on_eject_event: { + key: 'settings.launch_palette_on_eject_event', + type: chrome.settingsPrivate.PrefType.BOOLEAN, + value: false, + }, restore_last_lock_screen_note: { key: 'settings.restore_last_lock_screen_note', type: chrome.settingsPrivate.PrefType.BOOLEAN, @@ -1096,7 +1106,7 @@ suiteSetup(function() { // Always show stylus settings. loadTimeData.overrideValues({ - stylusAllowed: true, + hasInternalStylus: true, }); }); @@ -1159,6 +1169,35 @@ return !!element && element.offsetWidth > 0 && element.offsetHeight > 0; } + test('stylus tools prefs', function() { + // Both stylus tools prefs are intially false. + assertFalse(devicePage.prefs.settings.enable_stylus_tools.value); + assertFalse( + devicePage.prefs.settings.launch_palette_on_eject_event.value); + + // Since both prefs are intially false, the launch palette on eject pref + // toggle is disabled. + expectTrue(isVisible(stylusPage.$$('#enableStylusToolsToggle'))); + expectTrue( + isVisible(stylusPage.$$('#launchPaletteOnEjectEventToggle'))); + expectTrue( + stylusPage.$$('#launchPaletteOnEjectEventToggle').disabled); + expectFalse(devicePage.prefs.settings.enable_stylus_tools.value); + expectFalse( + devicePage.prefs.settings.launch_palette_on_eject_event.value); + + // Tapping the enable stylus tools pref causes the launch palette on + // eject pref toggle to not be disabled anymore. + MockInteractions.tap(stylusPage.$$('#enableStylusToolsToggle')); + expectTrue(devicePage.prefs.settings.enable_stylus_tools.value); + expectFalse( + stylusPage.$$('#launchPaletteOnEjectEventToggle').disabled); + MockInteractions.tap( + stylusPage.$$('#launchPaletteOnEjectEventToggle')); + expectTrue( + devicePage.prefs.settings.launch_palette_on_eject_event.value); + }); + test('choose first app if no preferred ones', function() { // Selector chooses the first value in list if there is no preferred // value set.
diff --git a/components/google/core/browser/google_url_tracker.h b/components/google/core/browser/google_url_tracker.h index e98af137..1b5017d 100644 --- a/components/google/core/browser/google_url_tracker.h +++ b/components/google/core/browser/google_url_tracker.h
@@ -81,7 +81,7 @@ // net::URLFetcherDelegate: void OnURLFetchComplete(const net::URLFetcher* source) override; - // NetworkChangeNotifier::IPAddressObserver: + // NetworkChangeNotifier::NetworkChangeObserver: void OnNetworkChanged( net::NetworkChangeNotifier::ConnectionType type) override;
diff --git a/components/machine_intelligence/proto/BUILD.gn b/components/machine_intelligence/proto/BUILD.gn index f2d9c9c..9c1d6a0 100644 --- a/components/machine_intelligence/proto/BUILD.gn +++ b/components/machine_intelligence/proto/BUILD.gn
@@ -6,7 +6,6 @@ proto_library("proto") { sources = [ - "contextual_search_ranker_model.proto", "generic_logistic_regression_model.proto", "ranker_example.proto", "ranker_model.proto",
diff --git a/components/machine_intelligence/proto/contextual_search_ranker_model.proto b/components/machine_intelligence/proto/contextual_search_ranker_model.proto deleted file mode 100644 index 79a793a..0000000 --- a/components/machine_intelligence/proto/contextual_search_ranker_model.proto +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright (c) 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// Assist Model for Contextual Search. - -syntax = "proto2"; - -option optimize_for = LITE_RUNTIME; - -import "generic_logistic_regression_model.proto"; - -package machine_intelligence; - -// Defines a Contextual Search Ranker Model. -message ContextualSearchRankerModel { - // A number that identifies the version of this model. - optional uint32 version = 1; - - oneof model_revision { - GenericLogisticRegressionModel generic_logistic_regression_model = 2; - } -} \ No newline at end of file
diff --git a/components/machine_intelligence/proto/ranker_model.proto b/components/machine_intelligence/proto/ranker_model.proto index 92178a3..adbfabf 100644 --- a/components/machine_intelligence/proto/ranker_model.proto +++ b/components/machine_intelligence/proto/ranker_model.proto
@@ -9,14 +9,14 @@ option optimize_for = LITE_RUNTIME; import "translate_ranker_model.proto"; -import "contextual_search_ranker_model.proto"; +import "generic_logistic_regression_model.proto"; package machine_intelligence; // Metadata for a ranker model instance. This data describes how the ranker // model should be interpreted/used. message RankerModelMetadata { - // An identifier denoting the type or purpose of this model. + // An identifier denoting the type or purpose of this model. E.g. "Translate". optional string name = 1; // An identifier denoting the specific instance of this model. For example: @@ -39,6 +39,9 @@ // instance of the model never expires. A new download can be triggered by // changing the configured source URL for the model loader. optional int64 cache_duration_sec = 5; + + // The version of the model. E.g. 20171027. + optional uint32 model_version = 6; } // Defines an envelope/wrapper for general models. @@ -48,6 +51,6 @@ oneof model { TranslateRankerModel translate = 2; - ContextualSearchRankerModel contextual_search = 3; + GenericLogisticRegressionModel logistic_regression = 3; } }
diff --git a/components/omnibox/browser/history_url_provider.cc b/components/omnibox/browser/history_url_provider.cc index bc9a43c..96e91400 100644 --- a/components/omnibox/browser/history_url_provider.cc +++ b/components/omnibox/browser/history_url_provider.cc
@@ -71,7 +71,11 @@ return a.url_info.visit_count() > b.url_info.visit_count(); // URLs that have been visited more recently are better. - return a.url_info.last_visit() > b.url_info.last_visit(); + if (a.url_info.last_visit() != b.url_info.last_visit()) + return a.url_info.last_visit() > b.url_info.last_visit(); + + // Use alphabetical order on the url spec as a tie-breaker. + return a.url_info.url().spec() > b.url_info.url().spec(); } // Sorts and dedups the given list of matches.
diff --git a/components/omnibox/browser/history_url_provider_unittest.cc b/components/omnibox/browser/history_url_provider_unittest.cc index c83fad1..a07a29a1 100644 --- a/components/omnibox/browser/history_url_provider_unittest.cc +++ b/components/omnibox/browser/history_url_provider_unittest.cc
@@ -870,19 +870,15 @@ EXPECT_LE(1400, matches_[0].relevance); EXPECT_LT(matches_[0].relevance, 1410); - const UrlAndLegalDefault expected3[] = { - { "http://intra/one", true }, - { "http://intra/three", true }, - { "http://intra/two", true } - }; + const UrlAndLegalDefault expected3[] = {{"http://intra/three", true}, + {"http://intra/one", true}, + {"http://intra/two", true}}; RunTest(ASCIIToUTF16("intra"), std::string(), false, expected3, arraysize(expected3)); - const UrlAndLegalDefault expected4[] = { - { "http://intra/one", true }, - { "http://intra/three", true }, - { "http://intra/two", true } - }; + const UrlAndLegalDefault expected4[] = {{"http://intra/three", true}, + {"http://intra/one", true}, + {"http://intra/two", true}}; RunTest(ASCIIToUTF16("intra/"), std::string(), false, expected4, arraysize(expected4)); @@ -1263,9 +1259,9 @@ ExpectFormattedFullMatch("WWW.hij", L"www.hij.com/\x2026\x0000", 0, 7); // Verify that matching in the subdomain-only preserves the subdomain. - ExpectFormattedFullMatch("ww", L"www.abc.def.com/\x2026\x0000", 0, 2); - ExpectFormattedFullMatch("https://ww", - L"https://www.abc.def.com/\x2026\x0000", 0, 10); + ExpectFormattedFullMatch("ww", L"www.hij.com/\x2026\x0000", 0, 2); + ExpectFormattedFullMatch("https://ww", L"https://www.hij.com/\x2026\x0000", 0, + 10); // Test individual feature flags as a sanity check. feature_list.reset(new base::test::ScopedFeatureList);
diff --git a/components/omnibox/browser/url_prefix.cc b/components/omnibox/browser/url_prefix.cc index 763036f..d4b2137 100644 --- a/components/omnibox/browser/url_prefix.cc +++ b/components/omnibox/browser/url_prefix.cc
@@ -53,11 +53,11 @@ CR_DEFINE_STATIC_LOCAL(URLPrefixes, prefixes, ()); if (prefixes.empty()) { // Keep this list in descending number of components. - prefixes.push_back(URLPrefix(base::ASCIIToUTF16("https://www."), 2)); prefixes.push_back(URLPrefix(base::ASCIIToUTF16("http://www."), 2)); + prefixes.push_back(URLPrefix(base::ASCIIToUTF16("https://www."), 2)); prefixes.push_back(URLPrefix(base::ASCIIToUTF16("ftp://www."), 2)); - prefixes.push_back(URLPrefix(base::ASCIIToUTF16("https://"), 1)); prefixes.push_back(URLPrefix(base::ASCIIToUTF16("http://"), 1)); + prefixes.push_back(URLPrefix(base::ASCIIToUTF16("https://"), 1)); prefixes.push_back(URLPrefix(base::ASCIIToUTF16("ftp://"), 1)); prefixes.push_back(URLPrefix(base::string16(), 0)); }
diff --git a/content/browser/blob_storage/blob_registry_wrapper.cc b/content/browser/blob_storage/blob_registry_wrapper.cc index 9057879..03b2708 100644 --- a/content/browser/blob_storage/blob_registry_wrapper.cc +++ b/content/browser/blob_storage/blob_registry_wrapper.cc
@@ -8,6 +8,7 @@ #include "content/browser/child_process_security_policy_impl.h" #include "content/public/common/content_features.h" #include "storage/browser/blob/blob_registry_impl.h" +#include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/fileapi/file_system_context.h" namespace content { @@ -72,7 +73,8 @@ scoped_refptr<storage::FileSystemContext> file_system_context) { DCHECK_CURRENTLY_ON(BrowserThread::IO); blob_registry_ = std::make_unique<storage::BlobRegistryImpl>( - blob_storage_context->context(), std::move(file_system_context)); + blob_storage_context->context()->AsWeakPtr(), + std::move(file_system_context)); } } // namespace content
diff --git a/content/network/OWNERS b/content/network/OWNERS index 3f8c53e..7e6f7eb 100644 --- a/content/network/OWNERS +++ b/content/network/OWNERS
@@ -1,10 +1,10 @@ ananta@chromium.org -asanka@chromium.org jam@chromium.org kinuko@chromium.org mmenke@chromium.org rdsmith@chromium.org scottmg@chromium.org +xunjieli@chromium.org yhirano@chromium.org yzshen@chromium.org
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc index 200e6722..962ea142 100644 --- a/content/public/test/render_view_test.cc +++ b/content/public/test/render_view_test.cc
@@ -9,7 +9,6 @@ #include <cctype> #include "base/location.h" -#include "base/memory/ptr_util.h" #include "base/metrics/field_trial.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" @@ -152,8 +151,9 @@ void RenderViewTest::RendererBlinkPlatformImplTestOverride::Initialize() { renderer_scheduler_ = blink::scheduler::RendererScheduler::Create(); - blink_platform_impl_.reset( - new RendererBlinkPlatformImplTestOverrideImpl(renderer_scheduler_.get())); + blink_platform_impl_ = + std::make_unique<RendererBlinkPlatformImplTestOverrideImpl>( + renderer_scheduler_.get()); } void RenderViewTest::RendererBlinkPlatformImplTestOverride::Shutdown() { @@ -161,7 +161,7 @@ blink_platform_impl_->Shutdown(); } -RenderViewTest::RenderViewTest() : view_(nullptr) { +RenderViewTest::RenderViewTest() { RenderFrameImpl::InstallCreateHook(&TestRenderFrame::CreateTestRenderFrame); } @@ -234,17 +234,18 @@ } void RenderViewTest::SetUp() { - test_io_thread_.reset(new base::TestIOThread(base::TestIOThread::kAutoStart)); - ipc_support_.reset(new mojo::edk::ScopedIPCSupport( + test_io_thread_ = + std::make_unique<base::TestIOThread>(base::TestIOThread::kAutoStart); + ipc_support_ = std::make_unique<mojo::edk::ScopedIPCSupport>( test_io_thread_->task_runner(), - mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST)); + mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST); // Subclasses can set render_thread_ with their own implementation before // calling RenderViewTest::SetUp(). // The render thread needs to exist before blink::Initialize. It also mirrors // the order on Chromium initialization. if (!render_thread_) - render_thread_.reset(new MockRenderThread()); + render_thread_ = std::make_unique<MockRenderThread>(); render_thread_->set_routing_id(kRouteId); render_thread_->set_new_window_routing_id(kNewWindowRouteId); render_thread_->set_new_window_main_frame_widget_routing_id( @@ -274,15 +275,16 @@ #endif #if defined(OS_MACOSX) - autorelease_pool_.reset(new base::mac::ScopedNSAutoreleasePool()); + autorelease_pool_ = std::make_unique<base::mac::ScopedNSAutoreleasePool>(); #endif - command_line_.reset(new base::CommandLine(base::CommandLine::NO_PROGRAM)); - field_trial_list_.reset(new base::FieldTrialList(nullptr)); + command_line_ = + std::make_unique<base::CommandLine>(base::CommandLine::NO_PROGRAM); + field_trial_list_ = std::make_unique<base::FieldTrialList>(nullptr); // We don't use the descriptor here anyways so it's ok to pass -1. base::FieldTrialList::CreateTrialsFromCommandLine( *command_line_, switches::kFieldTrialHandle, -1); - params_.reset(new MainFunctionParams(*command_line_)); - platform_.reset(new RendererMainPlatformDelegate(*params_)); + params_ = std::make_unique<MainFunctionParams>(*command_line_); + platform_ = std::make_unique<RendererMainPlatformDelegate>(*params_); platform_->PlatformInitialize(); // Setting flags and really doing anything with WebKit is fairly fragile and @@ -301,12 +303,13 @@ // ResourceBundle isn't initialized (since we have to use a diferent test // suite implementation than for content_unittests). For browser_tests, this // is already initialized. - if (!ui::ResourceBundle::HasSharedInstance()) + if (!ui::ResourceBundle::HasSharedInstance()) { ui::ResourceBundle::InitSharedInstanceWithLocale( "en-US", nullptr, ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES); + } - compositor_deps_.reset(new FakeCompositorDependencies); - mock_process_.reset(new MockRenderProcess); + compositor_deps_ = std::make_unique<FakeCompositorDependencies>(); + mock_process_ = std::make_unique<MockRenderProcess>(); mojom::CreateViewParamsPtr view_params = mojom::CreateViewParams::New(); view_params->opener_frame_route_id = MSG_ROUTING_NONE; @@ -328,11 +331,8 @@ view_params->min_size = gfx::Size(); view_params->max_size = gfx::Size(); - // This needs to pass the mock render thread to the view. - RenderViewImpl* view = - RenderViewImpl::Create(compositor_deps_.get(), std::move(view_params), - RenderWidget::ShowCallback()); - view_ = view; + view_ = RenderViewImpl::Create(compositor_deps_.get(), std::move(view_params), + RenderWidget::ShowCallback()); } void RenderViewTest::TearDown() { @@ -346,6 +346,8 @@ leak_detector->PrepareForLeakDetection(view_->GetWebView()->MainFrame()); + // |view_| is ref-counted and deletes itself during the RunUntilIdle() call + // below. view_ = nullptr; mock_process_.reset(); @@ -357,7 +359,7 @@ base::RunLoop().RunUntilIdle(); #if defined(OS_MACOSX) - autorelease_pool_.reset(NULL); + autorelease_pool_.reset(); #endif leak_detector->CollectGarbageAndReport(); @@ -412,27 +414,27 @@ SendInputEvent(gesture_event); } -const char* const kGetCoordinatesScript = - "(function() {" - " function GetCoordinates(elem) {" - " if (!elem)" - " return [ 0, 0];" - " var coordinates = [ elem.offsetLeft, elem.offsetTop];" - " var parent_coordinates = GetCoordinates(elem.offsetParent);" - " coordinates[0] += parent_coordinates[0];" - " coordinates[1] += parent_coordinates[1];" - " return [ Math.round(coordinates[0])," - " Math.round(coordinates[1])];" - " };" - " var elem = document.getElementById('$1');" - " if (!elem)" - " return null;" - " var bounds = GetCoordinates(elem);" - " bounds[2] = Math.round(elem.offsetWidth);" - " bounds[3] = Math.round(elem.offsetHeight);" - " return bounds;" - "})();"; gfx::Rect RenderViewTest::GetElementBounds(const std::string& element_id) { + static constexpr char kGetCoordinatesScript[] = + "(function() {" + " function GetCoordinates(elem) {" + " if (!elem)" + " return [ 0, 0];" + " var coordinates = [ elem.offsetLeft, elem.offsetTop];" + " var parent_coordinates = GetCoordinates(elem.offsetParent);" + " coordinates[0] += parent_coordinates[0];" + " coordinates[1] += parent_coordinates[1];" + " return [ Math.round(coordinates[0])," + " Math.round(coordinates[1])];" + " };" + " var elem = document.getElementById('$1');" + " if (!elem)" + " return null;" + " var bounds = GetCoordinates(elem);" + " bounds[2] = Math.round(elem.offsetWidth);" + " bounds[3] = Math.round(elem.offsetHeight);" + " return bounds;" + "})();"; std::vector<std::string> params; params.push_back(element_id); std::string script =
diff --git a/content/public/test/render_view_test.h b/content/public/test/render_view_test.h index 29cb0a9..4a84e5d 100644 --- a/content/public/test/render_view_test.h +++ b/content/public/test/render_view_test.h
@@ -190,14 +190,13 @@ // blink::WebLeakDetectorClient implementation. void OnLeakDetectionComplete(const Result& result) override; - protected: base::test::ScopedTaskEnvironment scoped_task_environment_; std::unique_ptr<FakeCompositorDependencies> compositor_deps_; std::unique_ptr<MockRenderProcess> mock_process_; // We use a naked pointer because we don't want to expose RenderViewImpl in // the embedder's namespace. - RenderView* view_; + RenderView* view_ = nullptr; RendererBlinkPlatformImplTestOverride blink_platform_impl_; std::unique_ptr<ContentClient> content_client_; std::unique_ptr<ContentBrowserClient> content_browser_client_;
diff --git a/content/public/test/test_renderer_host.h b/content/public/test/test_renderer_host.h index dfd9aee..eb6688e 100644 --- a/content/public/test/test_renderer_host.h +++ b/content/public/test/test_renderer_host.h
@@ -8,6 +8,8 @@ #include <stdint.h> #include <memory> +#include <string> +#include <vector> #include "base/macros.h" #include "base/message_loop/message_loop.h" @@ -121,6 +123,10 @@ virtual void SimulateFeaturePolicyHeader( blink::WebFeaturePolicyFeature feature, const std::vector<url::Origin>& whitelist) = 0; + + // Gets all the console messages requested via + // RenderFrameHost::AddMessageToConsole in this frame. + virtual const std::vector<std::string>& GetConsoleMessages() = 0; }; // An interface and utility for driving tests of RenderViewHost.
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc index 4522b910..7bd0c7a 100644 --- a/content/test/test_render_frame_host.cc +++ b/content/test/test_render_frame_host.cc
@@ -111,6 +111,12 @@ return static_cast<MockRenderProcessHost*>(RenderFrameHostImpl::GetProcess()); } +void TestRenderFrameHost::AddMessageToConsole(ConsoleMessageLevel level, + const std::string& message) { + console_messages_.push_back(message); + RenderFrameHostImpl::AddMessageToConsole(level, message); +} + void TestRenderFrameHost::InitializeRenderFrameIfNeeded() { if (!render_view_host()->IsRenderViewLive()) { render_view_host()->GetProcess()->Init(); @@ -305,6 +311,10 @@ OnDidSetFeaturePolicyHeader(header); } +const std::vector<std::string>& TestRenderFrameHost::GetConsoleMessages() { + return console_messages_; +} + void TestRenderFrameHost::SendNavigate(int nav_entry_id, bool did_create_new_entry, const GURL& url) {
diff --git a/content/test/test_render_frame_host.h b/content/test/test_render_frame_host.h index a81f0675..c569fbe 100644 --- a/content/test/test_render_frame_host.h +++ b/content/test/test_render_frame_host.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include <string> #include <vector> #include "base/macros.h" @@ -52,6 +53,8 @@ // RenderFrameHostImpl overrides (same values, but in Test*/Mock* types) TestRenderViewHost* GetRenderViewHost() override; MockRenderProcessHost* GetProcess() override; + void AddMessageToConsole(ConsoleMessageLevel level, + const std::string& message) override; // RenderFrameHostTester implementation. void InitializeRenderFrameIfNeeded() override; @@ -71,6 +74,7 @@ void SimulateFeaturePolicyHeader( blink::WebFeaturePolicyFeature feature, const std::vector<url::Origin>& whitelist) override; + const std::vector<std::string>& GetConsoleMessages() override; void SendNavigateWithReplacement(int nav_entry_id, bool did_create_new_entry, @@ -186,6 +190,9 @@ mojom::FrameNavigationControl* GetInternalNavigationControl(); + // Keeps a running vector of messages sent to AddMessageToConsole. + std::vector<std::string> console_messages_; + TestRenderFrameHostCreationObserver child_creation_observer_; std::string contents_mime_type_;
diff --git a/docs/updating_clang.md b/docs/updating_clang.md index ffda35d..c6f2375 100644 --- a/docs/updating_clang.md +++ b/docs/updating_clang.md
@@ -36,7 +36,7 @@ -b ios-device && \ git cl try -m tryserver.chromium.linux -b linux_chromium_chromeos_dbg_ng \ -b linux_chromium_chromeos_asan_rel_ng -b linux_chromium_msan_rel_ng \ - -b fuchsia -b linux_chromium_cfi_rel_ng && + -b linux_chromium_cfi_rel_ng && git cl try -m tryserver.blink -b linux_trusty_blink_rel ```
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 4fcb9b7b2..42ec9035 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -20293,12 +20293,13 @@ SkCanvas* canvas = sk_surface_->getCanvas(); SkMatrix original_ctm; cc::PlaybackParams playback_params(nullptr, original_ctm); + cc::PaintOp::DeserializeOptions options; int op_idx = 0; while (size > 4) { size_t skip = 0; cc::PaintOp* deserialized_op = cc::PaintOp::Deserialize( - buffer, size, &data[0], sizeof(cc::LargestPaintOp), &skip); + buffer, size, &data[0], sizeof(cc::LargestPaintOp), &skip, options); if (!deserialized_op) { LOG(ERROR) << "RasterCHROMIUM: bad op: " << op_idx; return error::kInvalidArguments;
diff --git a/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory_unittest.cc b/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory_unittest.cc index 268d5f8..f92ef043 100644 --- a/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory_unittest.cc +++ b/gpu/ipc/client/gpu_memory_buffer_impl_shared_memory_unittest.cc
@@ -14,30 +14,9 @@ GpuMemoryBufferImplTest, GpuMemoryBufferImplSharedMemory); -void BufferDestroyed(bool* destroyed, const gpu::SyncToken& sync_token) { - *destroyed = true; -} - -TEST(GpuMemoryBufferImplSharedMemoryTest, Create) { - const gfx::GpuMemoryBufferId kBufferId(1); - - gfx::Size buffer_size(8, 8); - gfx::BufferUsage usage = gfx::BufferUsage::GPU_READ; - - for (auto format : gfx::GetBufferFormatsForTesting()) { - bool destroyed = false; - std::unique_ptr<GpuMemoryBufferImplSharedMemory> buffer( - GpuMemoryBufferImplSharedMemory::Create( - kBufferId, buffer_size, format, usage, - base::Bind(&BufferDestroyed, base::Unretained(&destroyed)))); - ASSERT_TRUE(buffer); - EXPECT_EQ(buffer->GetFormat(), format); - - // Check if destruction callback is executed when deleting the buffer. - buffer.reset(); - ASSERT_TRUE(destroyed); - } -} +INSTANTIATE_TYPED_TEST_CASE_P(GpuMemoryBufferImplSharedMemory, + GpuMemoryBufferImplCreateTest, + GpuMemoryBufferImplSharedMemory); } // namespace } // namespace gpu
diff --git a/gpu/ipc/client/gpu_memory_buffer_impl_test_template.h b/gpu/ipc/client/gpu_memory_buffer_impl_test_template.h index 9723437..91cdc5d9 100644 --- a/gpu/ipc/client/gpu_memory_buffer_impl_test_template.h +++ b/gpu/ipc/client/gpu_memory_buffer_impl_test_template.h
@@ -57,6 +57,11 @@ } }; +// Subclass test case for tests that require a Create() method, +// not all implementations have that. +template <typename GpuMemoryBufferImplType> +class GpuMemoryBufferImplCreateTest : public testing::Test {}; + TYPED_TEST_CASE_P(GpuMemoryBufferImplTest); TYPED_TEST_P(GpuMemoryBufferImplTest, CreateFromHandle) { @@ -221,6 +226,36 @@ Map, PersistentMap); +TYPED_TEST_CASE_P(GpuMemoryBufferImplCreateTest); + +TYPED_TEST_P(GpuMemoryBufferImplCreateTest, Create) { + const gfx::GpuMemoryBufferId kBufferId(1); + const gfx::Size kBufferSize(8, 8); + gfx::BufferUsage usage = gfx::BufferUsage::GPU_READ; + + for (auto format : gfx::GetBufferFormatsForTesting()) { + if (!TypeParam::IsConfigurationSupported(format, usage)) + continue; + bool destroyed = false; + gfx::GpuMemoryBufferHandle handle; + std::unique_ptr<TypeParam> buffer(TypeParam::Create( + kBufferId, kBufferSize, format, usage, + base::Bind( + [](bool* destroyed, const gpu::SyncToken&) { *destroyed = true; }, + base::Unretained(&destroyed)))); + ASSERT_TRUE(buffer); + EXPECT_EQ(buffer->GetFormat(), format); + + // Check if destruction callback is executed when deleting the buffer. + buffer.reset(); + ASSERT_TRUE(destroyed); + } +} +// The GpuMemoryBufferImplCreateTest test case verifies behavior that is +// expected from a GpuMemoryBuffer Create() implementation in order to be +// conformant. +REGISTER_TYPED_TEST_CASE_P(GpuMemoryBufferImplCreateTest, Create); + } // namespace gpu #endif // GPU_IPC_CLIENT_GPU_MEMORY_BUFFER_IMPL_TEST_TEMPLATE_H_
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn index a1820394..8d177ca 100644 --- a/ios/chrome/app/BUILD.gn +++ b/ios/chrome/app/BUILD.gn
@@ -148,7 +148,6 @@ "//ios/chrome/app/startup:startup_basic", "//ios/chrome/app/strings", "//ios/chrome/browser", - "//ios/chrome/browser:browser_internal", "//ios/chrome/browser/bookmarks", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/browser_state:browser_state_impl", @@ -244,7 +243,6 @@ "//base", "//components/crash/core/common", "//ios/chrome/app/startup:startup_basic", - "//ios/chrome/browser:browser_internal", "//ios/chrome/browser/crash_report", "//ios/chrome/common", "//ios/testing/perf:startup",
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index e5d657ef..632d935 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -16,6 +16,7 @@ #include "base/feature_list.h" #include "base/files/file_path.h" #include "base/ios/block_types.h" +#include "base/ios/callback_counter.h" #import "base/mac/bind_objc_block.h" #include "base/mac/bundle_locations.h" #include "base/mac/foundation_util.h" @@ -64,7 +65,6 @@ #include "ios/chrome/browser/browser_state/chrome_browser_state_removal_controller.h" #import "ios/chrome/browser/browsing_data/browsing_data_removal_controller.h" #include "ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.h" -#include "ios/chrome/browser/callback_counter.h" #include "ios/chrome/browser/chrome_paths.h" #include "ios/chrome/browser/chrome_url_constants.h" #import "ios/chrome/browser/chrome_url_util.h"
diff --git a/ios/chrome/app/startup/BUILD.gn b/ios/chrome/app/startup/BUILD.gn index 7d1dd59..c9a4db1 100644 --- a/ios/chrome/app/startup/BUILD.gn +++ b/ios/chrome/app/startup/BUILD.gn
@@ -54,7 +54,6 @@ "//base", "//components/ntp_snippets", "//ios/chrome/browser", - "//ios/chrome/browser:browser_internal", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/first_run", "//ios/chrome/browser/net:net",
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index 63e476f..c728be72 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -226,7 +226,6 @@ testonly = true sources = [ "app_startup_parameters_unittest.mm", - "callback_counter_unittest.mm", "chrome_browser_provider_observer_bridge_unittest.mm", "chrome_url_util_unittest.mm", "crash_loop_detection_util_unittest.mm", @@ -237,7 +236,6 @@ ] deps = [ ":browser", - ":browser_internal", "//base", "//base/test:test_support", "//components/prefs", @@ -254,14 +252,3 @@ "//url", ] } - -source_set("browser_internal") { - configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "callback_counter.h", - "callback_counter.mm", - ] - deps = [ - "//base", - ] -}
diff --git a/ios/chrome/browser/browsing_data/BUILD.gn b/ios/chrome/browser/browsing_data/BUILD.gn index 4cd33ee..9cb5519a 100644 --- a/ios/chrome/browser/browsing_data/BUILD.gn +++ b/ios/chrome/browser/browsing_data/BUILD.gn
@@ -95,7 +95,6 @@ "//components/browsing_data/core", "//components/open_from_clipboard", "//components/signin/ios/browser", - "//ios/chrome/browser:browser_internal", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/sessions:serialisation", "//ios/chrome/browser/signin",
diff --git a/ios/chrome/browser/browsing_data/browsing_data_removal_controller.mm b/ios/chrome/browser/browsing_data/browsing_data_removal_controller.mm index 0f29f4dc..a596b31 100644 --- a/ios/chrome/browser/browsing_data/browsing_data_removal_controller.mm +++ b/ios/chrome/browser/browsing_data/browsing_data_removal_controller.mm
@@ -13,6 +13,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/containers/hash_tables.h" +#include "base/ios/callback_counter.h" #include "base/logging.h" #import "base/mac/bind_objc_block.h" #include "base/memory/ref_counted.h" @@ -21,7 +22,6 @@ #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/browsing_data/browsing_data_remover_helper.h" #include "ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.h" -#include "ios/chrome/browser/callback_counter.h" #include "ios/chrome/browser/sessions/session_util.h" #include "ios/chrome/browser/signin/account_consistency_service_factory.h" #import "ios/chrome/browser/snapshots/snapshots_util.h"
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_new_generation_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_new_generation_egtest.mm index 32e9755c6..51328ef 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_new_generation_egtest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmarks_new_generation_egtest.mm
@@ -8,6 +8,7 @@ #include <vector> #include "base/strings/sys_string_conversions.h" +#import "base/test/ios/wait_util.h" #include "base/test/scoped_feature_list.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/prefs/pref_service.h" @@ -725,9 +726,9 @@ performAction:grey_tap()]; // Wait so that the string is copied to clipboard. - testing::WaitUntilConditionOrTimeout(1, ^{ - return false; - }); + // TODO(crbug.com/780064): poll for pasteboard change instead. + base::test::ios::SpinRunLoopWithMinDelay(base::TimeDelta::FromSecondsD(1)); + // Verify general pasteboard has the URL copied. NSString* copiedString = [UIPasteboard generalPasteboard].string; GREYAssert([copiedString containsString:@"www.a.fr"],
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm index 04b7e7d..a57a729 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_cell.mm
@@ -324,7 +324,7 @@ initWithName:l10n_util::GetNSString(IDS_IOS_TAB_SWITCHER_CLOSE_TAB) target:self selector:@selector(closeButtonPressed)]; - [customActions addObject:customAction = nil]; + [customActions addObject:customAction]; return customActions; }
diff --git a/ios/chrome/test/app/BUILD.gn b/ios/chrome/test/app/BUILD.gn index a6377f8..de373c25 100644 --- a/ios/chrome/test/app/BUILD.gn +++ b/ios/chrome/test/app/BUILD.gn
@@ -53,7 +53,6 @@ "//ios/chrome/app/application_delegate:application_delegate_internal", "//ios/chrome/app/application_delegate:test_support", "//ios/chrome/browser", - "//ios/chrome/browser:browser_internal", "//ios/chrome/browser/autofill", "//ios/chrome/browser/bookmarks", "//ios/chrome/browser/browser_state",
diff --git a/ios/chrome/test/app/history_test_util.mm b/ios/chrome/test/app/history_test_util.mm index 500de21..1a0c4ad 100644 --- a/ios/chrome/test/app/history_test_util.mm +++ b/ios/chrome/test/app/history_test_util.mm
@@ -4,6 +4,7 @@ #import "ios/chrome/test/app/history_test_util.h" +#include "base/ios/callback_counter.h" #import "base/mac/bind_objc_block.h" #import "base/test/ios/wait_util.h" #include "components/browsing_data/core/browsing_data_utils.h" @@ -11,7 +12,6 @@ #import "ios/chrome/app/main_controller_private.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.h" -#include "ios/chrome/browser/callback_counter.h" #import "ios/chrome/test/app/chrome_test_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/test/app/static_html_view_test_util.mm b/ios/chrome/test/app/static_html_view_test_util.mm index 07d2347..3b2672f 100644 --- a/ios/chrome/test/app/static_html_view_test_util.mm +++ b/ios/chrome/test/app/static_html_view_test_util.mm
@@ -16,8 +16,12 @@ #error "This file requires ARC support." #endif +using testing::WaitUntilConditionOrTimeout; +using testing::kWaitForJSCompletionTimeout; + namespace chrome_test_util { +namespace { // Synchronously returns the result of executed JavaScript. id ExecuteScriptInStaticController( StaticHtmlViewController* html_view_controller, @@ -31,12 +35,13 @@ }]; // If a timeout is reached, then return |result|, which should be nil; - testing::WaitUntilConditionOrTimeout(testing::kWaitForJSCompletionTimeout, ^{ + bool completed = WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ return did_finish; }); - return result; + return completed ? result : nil; } +} // namespace // Returns the StaticHtmlViewController for the given |web_state|. If none is // found, it returns nil.
diff --git a/ios/chrome/test/app/tab_test_util.h b/ios/chrome/test/app/tab_test_util.h index 0fa3fad..31359851 100644 --- a/ios/chrome/test/app/tab_test_util.h +++ b/ios/chrome/test/app/tab_test_util.h
@@ -64,8 +64,8 @@ // Evicts the tabs associated with the non-current browser mode. void EvictOtherTabModelTabs(); -// Closes all incognito tabs. -void CloseAllIncognitoTabs(); +// Closes all incognito tabs. Return YES on success. +BOOL CloseAllIncognitoTabs(); // Returns the number of main tabs currently evicted. NSUInteger GetEvictedMainTabCount();
diff --git a/ios/chrome/test/app/tab_test_util.mm b/ios/chrome/test/app/tab_test_util.mm index 476f4f8..bd72660 100644 --- a/ios/chrome/test/app/tab_test_util.mm +++ b/ios/chrome/test/app/tab_test_util.mm
@@ -25,6 +25,8 @@ #error "This file requires ARC support." #endif +using testing::WaitUntilConditionOrTimeout; + namespace chrome_test_util { namespace { @@ -154,7 +156,7 @@ otherTabModel.webUsageEnabled = YES; } -void CloseAllIncognitoTabs() { +BOOL CloseAllIncognitoTabs() { MainController* main_controller = chrome_test_util::GetMainController(); DCHECK(main_controller); TabModel* tabModel = [[main_controller browserViewInformation] otrTabModel]; @@ -163,10 +165,11 @@ if (!IsIPadIdiom()) { // If the OTR BVC is active, wait until it isn't (since all of the // tabs are now closed) - testing::WaitUntilConditionOrTimeout(testing::kWaitForUIElementTimeout, ^{ + return WaitUntilConditionOrTimeout(testing::kWaitForUIElementTimeout, ^{ return !IsIncognitoMode(); }); } + return YES; } NSUInteger GetEvictedMainTabCount() {
diff --git a/ios/clean/chrome/app/BUILD.gn b/ios/clean/chrome/app/BUILD.gn index c76f8d8f..8ad002d 100644 --- a/ios/clean/chrome/app/BUILD.gn +++ b/ios/clean/chrome/app/BUILD.gn
@@ -85,7 +85,6 @@ "//ios/chrome/app/startup", "//ios/chrome/app/startup:startup_basic", "//ios/chrome/browser", - "//ios/chrome/browser:browser_internal", "//ios/chrome/browser/crash_report", "//ios/chrome/common", "//ios/testing/perf:startup",
diff --git a/ios/clean/chrome/app/steps/BUILD.gn b/ios/clean/chrome/app/steps/BUILD.gn index 92053f05..3e68ad9 100644 --- a/ios/clean/chrome/app/steps/BUILD.gn +++ b/ios/clean/chrome/app/steps/BUILD.gn
@@ -55,7 +55,6 @@ "//ios/chrome/app/startup", "//ios/chrome/app/startup:startup_basic", "//ios/chrome/browser", - "//ios/chrome/browser:browser_internal", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/browser_state:browser_state_impl", "//ios/chrome/browser/content_settings",
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index da3d3340..ed57c2a 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -269,6 +269,7 @@ "//ios/testing:ios_test_support", "//ios/testing:ocmock_support", "//ios/web/navigation", + "//ios/web/net/cookies", "//ios/web/public", "//ios/web/public/test", "//ios/web/public/test/fakes", @@ -288,6 +289,7 @@ sources = [ "net/cert_host_pair_unittest.cc", "net/cert_policy_unittest.cc", + "net/cookies/wk_cookie_util_unittest.mm", "net/crw_cert_verification_controller_unittest.mm", "net/crw_ssl_status_updater_unittest.mm", "net/request_group_util_unittest.mm",
diff --git a/ios/web/net/cookies/BUILD.gn b/ios/web/net/cookies/BUILD.gn new file mode 100644 index 0000000..fd3f993 --- /dev/null +++ b/ios/web/net/cookies/BUILD.gn
@@ -0,0 +1,20 @@ +# 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/build/config.gni") + +source_set("cookies") { + deps = [ + "//ios/web/web_state/ui:wk_web_view_configuration_provider", + ] + + sources = [ + "wk_cookie_util.h", + "wk_cookie_util.mm", + ] + + libs = [ "WebKit.framework" ] + + configs += [ "//build/config/compiler:enable_arc" ] +}
diff --git a/ios/web/net/cookies/wk_cookie_util.h b/ios/web/net/cookies/wk_cookie_util.h new file mode 100644 index 0000000..3971941 --- /dev/null +++ b/ios/web/net/cookies/wk_cookie_util.h
@@ -0,0 +1,24 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_NET_COOKIES_WK_COOKIE_UTIL_H_ +#define IOS_WEB_NET_COOKIES_WK_COOKIE_UTIL_H_ + +#include "base/mac/availability.h" + +@class WKHTTPCookieStore; + +namespace web { + +class BrowserState; + +// Returns WKHTTPCookieStore for the given BrowserState. If BrowserState is +// OffTheRecord then the resulting WKHTTPCookieStore will be a part of +// ephemeral WKWebsiteDataStore. +WKHTTPCookieStore* WKCookieStoreForBrowserState(BrowserState* browser_state) + API_AVAILABLE(ios(11.0)); + +} // namespace web + +#endif // IOS_WEB_NET_COOKIES_WK_COOKIE_UTIL_H_
diff --git a/ios/web/net/cookies/wk_cookie_util.mm b/ios/web/net/cookies/wk_cookie_util.mm new file mode 100644 index 0000000..2c75accb --- /dev/null +++ b/ios/web/net/cookies/wk_cookie_util.mm
@@ -0,0 +1,27 @@ +// 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/web/net/cookies/wk_cookie_util.h" + +#import <WebKit/WebKit.h> + +#import "ios/web/web_state/ui/wk_web_view_configuration_provider.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace web { + +WKHTTPCookieStore* WKCookieStoreForBrowserState(BrowserState* browser_state) { + if (@available(iOS 11, *)) { + WKWebViewConfigurationProvider& config_provider = + WKWebViewConfigurationProvider::FromBrowserState(browser_state); + WKWebViewConfiguration* config = config_provider.GetWebViewConfiguration(); + return config.websiteDataStore.httpCookieStore; + } + return nil; +} + +} // namespace web
diff --git a/ios/web/net/cookies/wk_cookie_util_unittest.mm b/ios/web/net/cookies/wk_cookie_util_unittest.mm new file mode 100644 index 0000000..f9405ac --- /dev/null +++ b/ios/web/net/cookies/wk_cookie_util_unittest.mm
@@ -0,0 +1,27 @@ +// 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/web/net/cookies/wk_cookie_util.h" + +#import <WebKit/WebKit.h> + +#import "ios/web/public/test/web_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace web { + +// Tests that web::WKCookieStoreForBrowserState returns valid WKHTTPCookieStore +// object on iOS 11. +using WKCookieUtilTest = WebTest; +TEST_F(WKCookieUtilTest, WKCookieStoreForBrowserState) { + if (@available(iOS 11, *)) { + WKHTTPCookieStore* store = WKCookieStoreForBrowserState(GetBrowserState()); + EXPECT_TRUE([store isKindOfClass:[WKHTTPCookieStore class]]); + } +} + +} // namespace web
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn index 8f1bbc1..74fc603 100644 --- a/ios/web_view/BUILD.gn +++ b/ios/web_view/BUILD.gn
@@ -24,6 +24,7 @@ # and CrNetChromeWebView frameworks. ios_web_view_public_headers = [ "public/ChromeWebView.h", + "public/cwv_autofill_suggestion.h", "public/cwv_export.h", "public/cwv_html_element.h", "public/cwv_navigation_action.h", @@ -58,6 +59,8 @@ "internal/app/application_context.h", "internal/app/web_view_io_thread.h", "internal/app/web_view_io_thread.mm", + "internal/autofill/cwv_autofill_suggestion.mm", + "internal/autofill/cwv_autofill_suggestion_internal.h", "internal/autofill/web_view_personal_data_manager_factory.cc", "internal/autofill/web_view_personal_data_manager_factory.h", "internal/content_settings/web_view_cookie_settings_factory.cc", @@ -87,22 +90,22 @@ "internal/pref_names.h", "internal/signin/ios_web_view_signin_client.h", "internal/signin/ios_web_view_signin_client.mm", - "internal/signin/web_view_account_fetcher_service_factory.cc", "internal/signin/web_view_account_fetcher_service_factory.h", - "internal/signin/web_view_account_tracker_service_factory.cc", + "internal/signin/web_view_account_fetcher_service_factory.mm", "internal/signin/web_view_account_tracker_service_factory.h", - "internal/signin/web_view_gaia_cookie_manager_service_factory.cc", + "internal/signin/web_view_account_tracker_service_factory.mm", "internal/signin/web_view_gaia_cookie_manager_service_factory.h", + "internal/signin/web_view_gaia_cookie_manager_service_factory.mm", "internal/signin/web_view_oauth2_token_service_factory.h", "internal/signin/web_view_oauth2_token_service_factory.mm", "internal/signin/web_view_profile_oauth2_token_service_ios_provider_impl.h", "internal/signin/web_view_profile_oauth2_token_service_ios_provider_impl.mm", - "internal/signin/web_view_signin_client_factory.cc", "internal/signin/web_view_signin_client_factory.h", - "internal/signin/web_view_signin_error_controller_factory.cc", + "internal/signin/web_view_signin_client_factory.mm", "internal/signin/web_view_signin_error_controller_factory.h", - "internal/signin/web_view_signin_manager_factory.cc", + "internal/signin/web_view_signin_error_controller_factory.mm", "internal/signin/web_view_signin_manager_factory.h", + "internal/signin/web_view_signin_manager_factory.mm", "internal/translate/cwv_translation_controller.mm", "internal/translate/cwv_translation_controller_internal.h", "internal/translate/cwv_translation_language_internal.h", @@ -154,6 +157,7 @@ "//base", "//components/autofill/core/browser", "//components/autofill/core/common", + "//components/autofill/ios/browser", "//components/content_settings/core/browser", "//components/flags_ui", "//components/infobars/core", @@ -226,6 +230,7 @@ test("ios_web_view_unittests") { testonly = true sources = [ + "internal/autofill/cwv_autofill_suggestion_unittest.mm", "internal/cwv_html_element_unittest.mm", "internal/cwv_preferences_unittest.mm", "internal/cwv_preview_element_info_unittest.mm",
diff --git a/ios/web_view/internal/autofill/cwv_autofill_suggestion.mm b/ios/web_view/internal/autofill/cwv_autofill_suggestion.mm new file mode 100644 index 0000000..d0013f0 --- /dev/null +++ b/ios/web_view/internal/autofill/cwv_autofill_suggestion.mm
@@ -0,0 +1,50 @@ +// 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/web_view/internal/autofill/cwv_autofill_suggestion_internal.h" + +#include "components/autofill/core/browser/popup_item_ids.h" +#import "components/autofill/ios/browser/form_suggestion.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation CWVAutofillSuggestion + +@synthesize formSuggestion = _formSuggestion; +@synthesize formName = _formName; +@synthesize fieldName = _fieldName; + +- (instancetype)initWithFormSuggestion:(FormSuggestion*)formSuggestion + formName:(NSString*)formName + fieldName:(NSString*)fieldName { + self = [super init]; + if (self) { + _formSuggestion = formSuggestion; + _formName = [formName copy]; + _fieldName = [fieldName copy]; + } + return self; +} + +#pragma mark - Public Methods + +- (NSString*)value { + return [_formSuggestion.value copy]; +} + +- (NSString*)displayDescription { + return [_formSuggestion.displayDescription copy]; +} + +#pragma mark - NSObject + +- (NSString*)debugDescription { + return [NSString stringWithFormat:@"%@ value: %@, displayDescription: %@", + super.debugDescription, self.value, + self.displayDescription]; +} + +@end
diff --git a/ios/web_view/internal/autofill/cwv_autofill_suggestion_internal.h b/ios/web_view/internal/autofill/cwv_autofill_suggestion_internal.h new file mode 100644 index 0000000..d284657 --- /dev/null +++ b/ios/web_view/internal/autofill/cwv_autofill_suggestion_internal.h
@@ -0,0 +1,28 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_VIEW_INTERNAL_AUTOFILL_CWV_AUTOFILL_SUGGESTION_INTERNAL_H_ +#define IOS_WEB_VIEW_INTERNAL_AUTOFILL_CWV_AUTOFILL_SUGGESTION_INTERNAL_H_ + +#import "ios/web_view/public/cwv_autofill_suggestion.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FormSuggestion; + +@interface CWVAutofillSuggestion () + +- (instancetype)initWithFormSuggestion:(FormSuggestion*)formSuggestion + formName:(NSString*)formName + fieldName:(NSString*)fieldName + NS_DESIGNATED_INITIALIZER; + +// The internal autofill form suggestion. +@property(nonatomic, readonly) FormSuggestion* formSuggestion; + +@end + +NS_ASSUME_NONNULL_END + +#endif // IOS_WEB_VIEW_INTERNAL_AUTOFILL_CWV_AUTOFILL_SUGGESTION_INTERNAL_H_
diff --git a/ios/web_view/internal/autofill/cwv_autofill_suggestion_unittest.mm b/ios/web_view/internal/autofill/cwv_autofill_suggestion_unittest.mm new file mode 100644 index 0000000..ddc5f01 --- /dev/null +++ b/ios/web_view/internal/autofill/cwv_autofill_suggestion_unittest.mm
@@ -0,0 +1,42 @@ +// 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/web_view/internal/autofill/cwv_autofill_suggestion_internal.h" + +#import <Foundation/Foundation.h> + +#import "components/autofill/ios/browser/form_suggestion.h" +#include "testing/gtest/include/gtest/gtest.h" +#import "testing/gtest_mac.h" +#include "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace ios_web_view { + +using CWVAutofillSuggestionTest = PlatformTest; + +// Tests CWVAutofillSuggestion initialization. +TEST_F(CWVAutofillSuggestionTest, Initialization) { + NSString* formName = @"TestFormName"; + NSString* fieldName = @"TestFieldName"; + FormSuggestion* formSuggestion = + [FormSuggestion suggestionWithValue:@"TestValue" + displayDescription:@"TestDisplayDescription" + icon:@"TestIcon" + identifier:0]; + CWVAutofillSuggestion* suggestion = + [[CWVAutofillSuggestion alloc] initWithFormSuggestion:formSuggestion + formName:formName + fieldName:fieldName]; + EXPECT_NSEQ(formName, suggestion.formName); + EXPECT_NSEQ(fieldName, suggestion.fieldName); + EXPECT_NSEQ(formSuggestion.displayDescription, suggestion.displayDescription); + EXPECT_NSEQ(formSuggestion.value, suggestion.value); + EXPECT_EQ(formSuggestion, suggestion.formSuggestion); +} + +} // namespace ios_web_view
diff --git a/ios/web_view/internal/signin/web_view_account_fetcher_service_factory.cc b/ios/web_view/internal/signin/web_view_account_fetcher_service_factory.mm similarity index 95% rename from ios/web_view/internal/signin/web_view_account_fetcher_service_factory.cc rename to ios/web_view/internal/signin/web_view_account_fetcher_service_factory.mm index 51ccf50..ac472dd 100644 --- a/ios/web_view/internal/signin/web_view_account_fetcher_service_factory.cc +++ b/ios/web_view/internal/signin/web_view_account_fetcher_service_factory.mm
@@ -17,6 +17,10 @@ #include "ios/web_view/internal/signin/web_view_signin_client_factory.h" #include "ios/web_view/internal/web_view_browser_state.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace ios_web_view { WebViewAccountFetcherServiceFactory::WebViewAccountFetcherServiceFactory()
diff --git a/ios/web_view/internal/signin/web_view_account_tracker_service_factory.cc b/ios/web_view/internal/signin/web_view_account_tracker_service_factory.mm similarity index 94% rename from ios/web_view/internal/signin/web_view_account_tracker_service_factory.cc rename to ios/web_view/internal/signin/web_view_account_tracker_service_factory.mm index a65af6c0..8f5bb72 100644 --- a/ios/web_view/internal/signin/web_view_account_tracker_service_factory.cc +++ b/ios/web_view/internal/signin/web_view_account_tracker_service_factory.mm
@@ -14,6 +14,10 @@ #include "ios/web_view/internal/signin/web_view_signin_client_factory.h" #include "ios/web_view/internal/web_view_browser_state.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace ios_web_view { WebViewAccountTrackerServiceFactory::WebViewAccountTrackerServiceFactory()
diff --git a/ios/web_view/internal/signin/web_view_gaia_cookie_manager_service_factory.cc b/ios/web_view/internal/signin/web_view_gaia_cookie_manager_service_factory.mm similarity index 95% rename from ios/web_view/internal/signin/web_view_gaia_cookie_manager_service_factory.cc rename to ios/web_view/internal/signin/web_view_gaia_cookie_manager_service_factory.mm index ca88640b..b903a05 100644 --- a/ios/web_view/internal/signin/web_view_gaia_cookie_manager_service_factory.cc +++ b/ios/web_view/internal/signin/web_view_gaia_cookie_manager_service_factory.mm
@@ -16,6 +16,10 @@ #include "ios/web_view/internal/signin/web_view_signin_client_factory.h" #include "ios/web_view/internal/web_view_browser_state.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace ios_web_view { WebViewGaiaCookieManagerServiceFactory::WebViewGaiaCookieManagerServiceFactory()
diff --git a/ios/web_view/internal/signin/web_view_signin_client_factory.cc b/ios/web_view/internal/signin/web_view_signin_client_factory.mm similarity index 95% rename from ios/web_view/internal/signin/web_view_signin_client_factory.cc rename to ios/web_view/internal/signin/web_view_signin_client_factory.mm index d6073d7..609ad2c6 100644 --- a/ios/web_view/internal/signin/web_view_signin_client_factory.cc +++ b/ios/web_view/internal/signin/web_view_signin_client_factory.mm
@@ -15,6 +15,10 @@ #include "ios/web_view/internal/signin/web_view_signin_error_controller_factory.h" #include "ios/web_view/internal/web_view_browser_state.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace ios_web_view { // static
diff --git a/ios/web_view/internal/signin/web_view_signin_error_controller_factory.cc b/ios/web_view/internal/signin/web_view_signin_error_controller_factory.mm similarity index 92% rename from ios/web_view/internal/signin/web_view_signin_error_controller_factory.cc rename to ios/web_view/internal/signin/web_view_signin_error_controller_factory.mm index 3a888bd..a2f25c7 100644 --- a/ios/web_view/internal/signin/web_view_signin_error_controller_factory.cc +++ b/ios/web_view/internal/signin/web_view_signin_error_controller_factory.mm
@@ -11,6 +11,10 @@ #include "components/signin/core/browser/signin_error_controller.h" #include "ios/web_view/internal/web_view_browser_state.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace ios_web_view { // static
diff --git a/ios/web_view/internal/signin/web_view_signin_manager_factory.cc b/ios/web_view/internal/signin/web_view_signin_manager_factory.mm similarity index 96% rename from ios/web_view/internal/signin/web_view_signin_manager_factory.cc rename to ios/web_view/internal/signin/web_view_signin_manager_factory.mm index 8ddf187..6369b278 100644 --- a/ios/web_view/internal/signin/web_view_signin_manager_factory.cc +++ b/ios/web_view/internal/signin/web_view_signin_manager_factory.mm
@@ -21,6 +21,10 @@ #include "ios/web_view/internal/signin/web_view_signin_client_factory.h" #include "ios/web_view/internal/web_view_browser_state.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace ios_web_view { WebViewSigninManagerFactory::WebViewSigninManagerFactory()
diff --git a/ios/web_view/public/ChromeWebView.h b/ios/web_view/public/ChromeWebView.h index 1ac3892..875c85f 100644 --- a/ios/web_view/public/ChromeWebView.h +++ b/ios/web_view/public/ChromeWebView.h
@@ -9,6 +9,7 @@ // ChromeWebView. Framework style imports can't be used because multiple // frameworks are built from ios/web_view with different output names. +#import "cwv_autofill_suggestion.h" #import "cwv_export.h" #import "cwv_html_element.h" #import "cwv_navigation_action.h"
diff --git a/ios/web_view/test/web_view_test_util.mm b/ios/web_view/test/web_view_test_util.mm index f3141930..cbd93a74 100644 --- a/ios/web_view/test/web_view_test_util.mm +++ b/ios/web_view/test/web_view_test_util.mm
@@ -14,6 +14,7 @@ #endif using testing::WaitUntilConditionOrTimeout; +using testing::kWaitForJSCompletionTimeout; namespace ios_web_view { namespace test { @@ -46,24 +47,24 @@ } id EvaluateJavaScript(CWVWebView* web_view, NSString* script, NSError** error) { - __block bool did_complete = false; + __block bool callback_called = false; __block id evaluation_result = nil; __block id evaluation_error = nil; [web_view evaluateJavaScript:script completionHandler:^(id local_result, NSError* local_error) { - did_complete = true; + callback_called = true; evaluation_result = [local_result copy]; evaluation_error = [local_error copy]; }]; - WaitUntilConditionOrTimeout(testing::kWaitForJSCompletionTimeout, ^{ - return did_complete; + bool completed = WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ + return callback_called; }); if (error) *error = evaluation_error; - return evaluation_result; + return completed ? evaluation_result : nil; } bool WaitForWebViewContainingTextOrTimeout(CWVWebView* web_view,
diff --git a/storage/browser/blob/blob_registry_impl.cc b/storage/browser/blob/blob_registry_impl.cc index bf25ac1..5d68143 100644 --- a/storage/browser/blob/blob_registry_impl.cc +++ b/storage/browser/blob/blob_registry_impl.cc
@@ -54,7 +54,7 @@ const GURL& url) { blink::mojom::BlobURLHandlePtr ptr; mojo::MakeStrongBinding( - base::WrapUnique(new BlobURLHandleImpl(context, url)), + base::WrapUnique(new BlobURLHandleImpl(std::move(context), url)), mojo::MakeRequest(&ptr)); return ptr; } @@ -103,7 +103,7 @@ const std::string& uuid() const { return builder_.uuid(); } private: - BlobStorageContext* context() const { return blob_registry_->context_; } + BlobStorageContext* context() const { return blob_registry_->context_.get(); } // Marks this blob as broken. If an optional |bad_message_reason| is provided, // this will also report a BadMessage on the binding over which the initial @@ -115,7 +115,7 @@ DCHECK_EQ(bad_message_reason.empty(), !BlobStatusIsBadIPC(reason)); // The blob might no longer have any references, in which case it may no // longer exist. If that happens just skip calling cancel. - if (context()->registry().HasEntry(uuid())) + if (context() && context()->registry().HasEntry(uuid())) context()->CancelBuildingBlob(uuid(), reason); if (!bad_message_reason.empty()) std::move(bad_message_callback_).Run(bad_message_reason); @@ -199,6 +199,11 @@ }; void BlobRegistryImpl::BlobUnderConstruction::StartTransportation() { + if (!context()) { + MarkAsFinishedAndDeleteSelf(); + return; + } + size_t blob_count = 0; for (size_t i = 0; i < elements_.size(); ++i) { const auto& element = elements_[i]; @@ -282,6 +287,11 @@ } #endif + if (!context()) { + MarkAsFinishedAndDeleteSelf(); + return; + } + if (referenced_blob_uuids_.size() == 0) { ResolvedAllBlobDependencies(); return; @@ -321,6 +331,11 @@ DCHECK_EQ(resolved_blob_uuid_count_, referenced_blob_uuids_.size()); DCHECK_EQ(ready_dependent_blob_count_, referenced_blob_uuids_.size()); + if (!context()) { + MarkAsFinishedAndDeleteSelf(); + return; + } + auto blob_uuid_it = referenced_blob_uuids_.begin(); for (const auto& element : elements_) { if (element->is_bytes()) { @@ -378,6 +393,11 @@ void BlobRegistryImpl::BlobUnderConstruction::TransportComplete( BlobStatus result) { + if (!context()) { + MarkAsFinishedAndDeleteSelf(); + return; + } + // The blob might no longer have any references, in which case it may no // longer exist. If that happens just skip calling Complete. // TODO(mek): Stop building sooner if a blob is no longer referenced. @@ -417,9 +437,9 @@ #endif BlobRegistryImpl::BlobRegistryImpl( - BlobStorageContext* context, + base::WeakPtr<BlobStorageContext> context, scoped_refptr<FileSystemContext> file_system_context) - : context_(context), + : context_(std::move(context)), file_system_context_(std::move(file_system_context)), weak_ptr_factory_(this) {} @@ -438,6 +458,11 @@ const std::string& content_disposition, std::vector<blink::mojom::DataElementPtr> elements, RegisterCallback callback) { + if (!context_) { + std::move(callback).Run(); + return; + } + if (uuid.empty() || context_->registry().HasEntry(uuid) || base::ContainsKey(blobs_under_construction_, uuid)) { bindings_.ReportBadMessage("Invalid UUID passed to BlobRegistry::Register"); @@ -496,6 +521,11 @@ void BlobRegistryImpl::GetBlobFromUUID(blink::mojom::BlobRequest blob, const std::string& uuid, GetBlobFromUUIDCallback callback) { + if (!context_) { + std::move(callback).Run(); + return; + } + if (uuid.empty()) { bindings_.ReportBadMessage( "Invalid UUID passed to BlobRegistry::GetBlobFromUUID"); @@ -533,9 +563,9 @@ const std::string& uuid) { // |blob| is unused, but is passed here to be kept alive until // RegisterBlobURL increments the refcount of it via the uuid. - context_->RegisterPublicBlobURL(url, uuid); - std::move(callback).Run( - BlobURLHandleImpl::Create(context_->AsWeakPtr(), url)); + if (context_) + context_->RegisterPublicBlobURL(url, uuid); + std::move(callback).Run(BlobURLHandleImpl::Create(context_, url)); } } // namespace storage
diff --git a/storage/browser/blob/blob_registry_impl.h b/storage/browser/blob/blob_registry_impl.h index 39906911..d302f4d9 100644 --- a/storage/browser/blob/blob_registry_impl.h +++ b/storage/browser/blob/blob_registry_impl.h
@@ -28,7 +28,7 @@ virtual bool CanCommitURL(const GURL& url) = 0; }; - BlobRegistryImpl(BlobStorageContext* context, + BlobRegistryImpl(base::WeakPtr<BlobStorageContext> context, scoped_refptr<FileSystemContext> file_system_context); ~BlobRegistryImpl() override; @@ -61,7 +61,7 @@ class BlobUnderConstruction; - BlobStorageContext* context_; + base::WeakPtr<BlobStorageContext> context_; scoped_refptr<FileSystemContext> file_system_context_; mojo::BindingSet<blink::mojom::BlobRegistry, std::unique_ptr<Delegate>>
diff --git a/storage/browser/blob/blob_registry_impl_unittest.cc b/storage/browser/blob/blob_registry_impl_unittest.cc index de044ca..6b385a2 100644 --- a/storage/browser/blob/blob_registry_impl_unittest.cc +++ b/storage/browser/blob/blob_registry_impl_unittest.cc
@@ -105,7 +105,7 @@ std::vector<URLRequestAutoMountHandler>(), data_dir_.GetPath(), FileSystemOptions(FileSystemOptions::PROFILE_MODE_INCOGNITO, std::vector<std::string>(), nullptr)); - registry_impl_ = base::MakeUnique<BlobRegistryImpl>(context_.get(), + registry_impl_ = base::MakeUnique<BlobRegistryImpl>(context_->AsWeakPtr(), file_system_context_); auto delegate = base::MakeUnique<MockDelegate>(); delegate_ptr_ = delegate.get();
diff --git a/third_party/WebKit/LayoutTests/fast/forms/text/input-appearance-autocomplete-very-long-value-expected.html b/third_party/WebKit/LayoutTests/fast/forms/text/input-appearance-autocomplete-very-long-value-expected.html new file mode 100644 index 0000000..a6d407aa --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/forms/text/input-appearance-autocomplete-very-long-value-expected.html
@@ -0,0 +1,6 @@ +<input id="input" value="Guy WithAVeryLongLastNameThatCouldWrap" style="width: 99px" > +<script> +input.focus(); +input.setSelectionRange(0,0); +internals.setAutofilled(input, true); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/forms/text/input-appearance-autocomplete-very-long-value.html b/third_party/WebKit/LayoutTests/fast/forms/text/input-appearance-autocomplete-very-long-value.html new file mode 100644 index 0000000..f1febec --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/forms/text/input-appearance-autocomplete-very-long-value.html
@@ -0,0 +1,7 @@ +<input id="input" > +<script> +input.focus(); +internals.setSuggestedValue(input, 'Guy WithAVeryLongLastNameThatCouldWrap'); +internals.setAutofilled(input, true); +input.style.width = '99px'; +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/text/input-appearance-autocomplete-with-initial-value-expected.html b/third_party/WebKit/LayoutTests/fast/forms/text/input-appearance-autocomplete-with-initial-value-expected.html new file mode 100644 index 0000000..18a14ac5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/forms/text/input-appearance-autocomplete-with-initial-value-expected.html
@@ -0,0 +1,6 @@ +<input id="input" value="hello" style="width: 99px" > +<script> +input.focus(); +input.setSelectionRange(0,0); +internals.setAutofilled(input, true); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/forms/text/input-appearance-autocomplete-with-initial-value.html b/third_party/WebKit/LayoutTests/fast/forms/text/input-appearance-autocomplete-with-initial-value.html new file mode 100644 index 0000000..b791583 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/forms/text/input-appearance-autocomplete-with-initial-value.html
@@ -0,0 +1,8 @@ +<input id="input" > +<script> +input.focus(); +input.value = "initial value"; +internals.setSuggestedValue(input, 'hello'); +internals.setAutofilled(input, true); +input.style.width = '99px'; +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/shapes/crash-allocating-very-large-raster-shape-expected.txt b/third_party/WebKit/LayoutTests/fast/shapes/crash-allocating-very-large-raster-shape-expected.txt new file mode 100644 index 0000000..8c47c16d --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/shapes/crash-allocating-very-large-raster-shape-expected.txt
@@ -0,0 +1,24 @@ +A +B + +C + +D + +E + +F + +G + +H + +I + +KKKKKKKKKKKKKKKKKKKKKKKKK + +L + +M + +
diff --git a/third_party/WebKit/LayoutTests/fast/shapes/crash-allocating-very-large-raster-shape.html b/third_party/WebKit/LayoutTests/fast/shapes/crash-allocating-very-large-raster-shape.html new file mode 100644 index 0000000..c8161c8d --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/shapes/crash-allocating-very-large-raster-shape.html
@@ -0,0 +1,44 @@ +<!-- Without the the associated fix, crashes only in Win 32 ASAN. --> +<!-- The exact width of the column also matters. --> +<script> + if (window.testRunner) { + testRunner.dumpAsText(); + } +</script> +<style> + * { + /* Margin size is important. Just enough to crash but not enough to hit + the check for "too big to allocate an image" + */ + margin: 41310px auto 90 auto; + shape-outside: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'></svg>"); + } +</style> +<body style="column-width:24em; column-gap:2em"> + <div style="float:left;"> + <div>A + <p>B + <p>C + <p>D + <p>E + <p>F + <p>G + <p>H + <p>I + <p>KKKKKKKKKKKKKKKKKKKKKKKKK + <p>L + <p>M + </p> + </p> + </p> + </p> + </p> + </p> + </p> + </p> + </p> + </p> + </p> + </div> + </div> +</body>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/background-attachment-local-composited-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/background-attachment-local-composited-expected.txt new file mode 100644 index 0000000..87edf08 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/background-attachment-local-composited-expected.txt
@@ -0,0 +1,72 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV id='container'", + "position": [8, 8], + "bounds": [400, 400], + "backgroundColor": "#0000FF" + }, + { + "name": "Scrolling Layer", + "position": [8, 8], + "bounds": [400, 400], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [8, 8], + "bounds": [400, 2000], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "rect": [0, 500, 400, 1500], + "reason": "incremental" + } + ], + "transform": 1 + }, + { + "name": "Overflow Controls Host Layer", + "position": [8, 8], + "bounds": [400, 400], + "drawsContent": false + }, + { + "name": "Horizontal Scrollbar Layer", + "position": [8, 408], + "bounds": [400, 0] + }, + { + "name": "Vertical Scrollbar Layer", + "position": [408, 8], + "bounds": [0, 400] + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, -1600, 0, 1] + ], + "flattenInheritedTransform": false + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "incremental" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/background-attachment-local-equivalent-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/background-attachment-local-equivalent-expected.txt new file mode 100644 index 0000000..87edf08 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v175/paint/invalidation/compositing/background-attachment-local-equivalent-expected.txt
@@ -0,0 +1,72 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV id='container'", + "position": [8, 8], + "bounds": [400, 400], + "backgroundColor": "#0000FF" + }, + { + "name": "Scrolling Layer", + "position": [8, 8], + "bounds": [400, 400], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [8, 8], + "bounds": [400, 2000], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "paintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "rect": [0, 500, 400, 1500], + "reason": "incremental" + } + ], + "transform": 1 + }, + { + "name": "Overflow Controls Host Layer", + "position": [8, 8], + "bounds": [400, 400], + "drawsContent": false + }, + { + "name": "Horizontal Scrollbar Layer", + "position": [8, 408], + "bounds": [400, 0] + }, + { + "name": "Vertical Scrollbar Layer", + "position": [408, 8], + "bounds": [0, 400] + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, -1600, 0, 1] + ], + "flattenInheritedTransform": false + } + ], + "objectPaintInvalidations": [ + { + "object": "Scrolling Contents Layer", + "reason": "incremental" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/invalidate-invisible-element-expected.html b/third_party/WebKit/LayoutTests/paint/invalidation/invalidate-invisible-element-expected.html index d41a36e..7982cf0 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/invalidate-invisible-element-expected.html +++ b/third_party/WebKit/LayoutTests/paint/invalidation/invalidate-invisible-element-expected.html
@@ -5,6 +5,6 @@ style="position: absolute; top: 300px; left: 200px; width: 200px; height: 200px; - background-color: redl "></div> + background-color: red"></div> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/invalidate-invisible-element.html b/third_party/WebKit/LayoutTests/paint/invalidation/invalidate-invisible-element.html index ccd2006..f4477f4 100644 --- a/third_party/WebKit/LayoutTests/paint/invalidation/invalidate-invisible-element.html +++ b/third_party/WebKit/LayoutTests/paint/invalidation/invalidate-invisible-element.html
@@ -21,6 +21,6 @@ position: absolute; top: 200px; left: 200px; width: 200px; height: 200px; - background-color: redl "></div> + background-color: red"></div> </body> </html>
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index ff33ff6..422f30fb 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1565,6 +1565,7 @@ "imagebitmap/ImageBitmapTest.cpp", "input/EventHandlerTest.cpp", "input/ImeOnFocusTest.cpp", + "input/PointerEventManagerTest.cpp", "input/ScrollBoundaryBehaviorTest.cpp", "input/TouchActionTest.cpp", "input/TouchEventManagerTest.cpp",
diff --git a/third_party/WebKit/Source/core/css/html.css b/third_party/WebKit/Source/core/css/html.css index ef11631..6e7559bc 100644 --- a/third_party/WebKit/Source/core/css/html.css +++ b/third_party/WebKit/Source/core/css/html.css
@@ -517,6 +517,12 @@ -webkit-user-modify: read-only !important; } +input::-internal-input-suggested { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + input[type="password" i] { -webkit-text-security: disc !important; }
diff --git a/third_party/WebKit/Source/core/events/PointerEventFactory.cpp b/third_party/WebKit/Source/core/events/PointerEventFactory.cpp index 7e20eb0..bacc76b 100644 --- a/third_party/WebKit/Source/core/events/PointerEventFactory.cpp +++ b/third_party/WebKit/Source/core/events/PointerEventFactory.cpp
@@ -374,18 +374,7 @@ } PointerEvent* PointerEventFactory::CreatePointerCancelEvent( - const WebPointerEvent& event) { - DCHECK_EQ(event.GetType(), WebInputEvent::Type::kPointerCancel); - int pointer_id = GetPointerEventId(event); - - return CreatePointerCancelEvent( - pointer_id, event.pointer_type, - TimeTicks::FromSeconds(event.TimeStampSeconds())); -} - -PointerEvent* PointerEventFactory::CreatePointerCancelEvent( const int pointer_id, - const WebPointerProperties::PointerType pointer_type, TimeTicks platfrom_time_stamp) { DCHECK(pointer_id_mapping_.Contains(pointer_id)); pointer_id_mapping_.Set( @@ -396,8 +385,8 @@ PointerEventInit pointer_event_init; pointer_event_init.setPointerId(pointer_id); - pointer_event_init.setPointerType( - PointerTypeNameForWebPointPointerType(pointer_type)); + pointer_event_init.setPointerType(PointerTypeNameForWebPointPointerType( + pointer_id_mapping_.at(pointer_id).incoming_id.GetPointerType())); pointer_event_init.setIsPrimary(IsPrimary(pointer_id)); SetEventSpecificFields(pointer_event_init, EventTypeNames::pointercancel);
diff --git a/third_party/WebKit/Source/core/events/PointerEventFactory.h b/third_party/WebKit/Source/core/events/PointerEventFactory.h index 0d037ed8..1f992a9 100644 --- a/third_party/WebKit/Source/core/events/PointerEventFactory.h +++ b/third_party/WebKit/Source/core/events/PointerEventFactory.h
@@ -42,11 +42,8 @@ LocalFrame*, DOMWindow*); - PointerEvent* CreatePointerCancelEvent(const WebPointerEvent&); - PointerEvent* CreatePointerCancelEvent( const int pointer_id, - const WebPointerProperties::PointerType, TimeTicks platfrom_time_stamp); // For creating capture events (i.e got/lostpointercapture)
diff --git a/third_party/WebKit/Source/core/events/PointerEventFactoryTest.cpp b/third_party/WebKit/Source/core/events/PointerEventFactoryTest.cpp index 219e2a39..883fcdf1 100644 --- a/third_party/WebKit/Source/core/events/PointerEventFactoryTest.cpp +++ b/third_party/WebKit/Source/core/events/PointerEventFactoryTest.cpp
@@ -35,10 +35,10 @@ class PointerEventFactoryTest : public ::testing::Test { protected: void SetUp() override; - PointerEvent* CreateAndCheckTouchCancel(WebPointerProperties::PointerType, - int raw_id, - int unique_id, - bool is_primary); + PointerEvent* CreateAndCheckPointerCancel(WebPointerProperties::PointerType, + int raw_id, + int unique_id, + bool is_primary); PointerEvent* CreateAndCheckTouchEvent( WebPointerProperties::PointerType, int raw_id, @@ -53,12 +53,6 @@ bool is_primary, WebInputEvent::Modifiers = WebInputEvent::kNoModifiers, size_t coalesced_event_count = 0); - PointerEvent* CreateAndCheckPointerCancelEvent( - WebPointerProperties::PointerType, - int raw_id, - int unique_id, - bool is_primary, - WebInputEvent::Modifiers = WebInputEvent::kNoModifiers); void CreateAndCheckPointerTransitionEvent(PointerEvent*, const AtomicString&); void CheckScrollCapablePointers(const std::set<int>& expected); @@ -109,19 +103,21 @@ time_stamp_seconds_ = platform_time_stamp; } -PointerEvent* PointerEventFactoryTest::CreateAndCheckTouchCancel( +PointerEvent* PointerEventFactoryTest::CreateAndCheckPointerCancel( WebPointerProperties::PointerType pointer_type, int raw_id, int unique_id, bool is_primary) { - TimeTicks now = TimeTicks::Now(); PointerEvent* pointer_event = pointer_event_factory_.CreatePointerCancelEvent( - unique_id, pointer_type, now); + unique_id, TimeTicks::FromSeconds(WebInputEvent::kTimeStampForTesting)); + EXPECT_EQ("pointercancel", pointer_event->type()); EXPECT_EQ(unique_id, pointer_event->pointerId()); EXPECT_EQ(is_primary, pointer_event->isPrimary()); EXPECT_EQ(PointerTypeNameForWebPointPointerType(pointer_type), pointer_event->pointerType()); - EXPECT_EQ(now, pointer_event->PlatformTimeStamp()); + EXPECT_EQ(TimeTicks::FromSeconds(WebInputEvent::kTimeStampForTesting), + pointer_event->PlatformTimeStamp()); + return pointer_event; } @@ -181,28 +177,6 @@ return pointer_event; } -PointerEvent* PointerEventFactoryTest::CreateAndCheckPointerCancelEvent( - WebPointerProperties::PointerType pointer_type, - int raw_id, - int unique_id, - bool is_primary, - WebInputEvent::Modifiers modifiers) { - PointerEvent* pointer_event = pointer_event_factory_.CreatePointerCancelEvent( - WebPointerEvent(WebInputEvent::Type::kPointerCancel, - PointerEventFactoryTest::WebMouseEventBuilder( - pointer_type, raw_id, modifiers, - WebInputEvent::kTimeStampForTesting))); - EXPECT_EQ("pointercancel", pointer_event->type()); - EXPECT_EQ(unique_id, pointer_event->pointerId()); - EXPECT_EQ(is_primary, pointer_event->isPrimary()); - EXPECT_EQ(TimeTicks::FromSeconds(WebInputEvent::kTimeStampForTesting), - pointer_event->PlatformTimeStamp()); - const char* expected_pointer_type = - PointerTypeNameForWebPointPointerType(pointer_type); - EXPECT_EQ(expected_pointer_type, pointer_event->pointerType()); - return pointer_event; -} - PointerEvent* PointerEventFactoryTest::CreateAndCheckMouseEvent( WebPointerProperties::PointerType pointer_type, int raw_id, @@ -282,8 +256,8 @@ EXPECT_TRUE(pointer_event_factory_.IsActive(expected_mouse_id_)); EXPECT_TRUE(pointer_event_factory_.IsActiveButtonsState(expected_mouse_id_)); - CreateAndCheckPointerCancelEvent(WebPointerProperties::PointerType::kMouse, 0, - expected_mouse_id_, true); + CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kMouse, 0, + expected_mouse_id_, true); EXPECT_TRUE(pointer_event_factory_.IsActive(expected_mouse_id_)); EXPECT_FALSE(pointer_event_factory_.IsActiveButtonsState(expected_mouse_id_)); @@ -391,8 +365,8 @@ CreateAndCheckTouchEvent(WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_ + 1, true); - CreateAndCheckTouchCancel(WebPointerProperties::PointerType::kTouch, 0, - mapped_id_start_ + 1, true); + CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kTouch, 0, + mapped_id_start_ + 1, true); EXPECT_TRUE(pointer_event_factory_.IsActive(mapped_id_start_ + 1)); EXPECT_FALSE( @@ -507,8 +481,8 @@ mapped_id_start_ + 3, false); CreateAndCheckMouseEvent(WebPointerProperties::PointerType::kPen, 0, mapped_id_start_ + 3, false); - CreateAndCheckTouchCancel(WebPointerProperties::PointerType::kPen, 0, - mapped_id_start_ + 3, false); + CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kPen, 0, + mapped_id_start_ + 3, false); pointer_event_factory_.Clear(); @@ -520,10 +494,10 @@ mapped_id_start_, true); CreateAndCheckMouseEvent(WebPointerProperties::PointerType::kPen, 0, mapped_id_start_ + 1, false); - CreateAndCheckTouchCancel(WebPointerProperties::PointerType::kPen, 1, - mapped_id_start_, true); - CreateAndCheckTouchCancel(WebPointerProperties::PointerType::kPen, 0, - mapped_id_start_ + 1, false); + CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kPen, 1, + mapped_id_start_, true); + CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kPen, 0, + mapped_id_start_ + 1, false); } TEST_F(PointerEventFactoryTest, OutOfRange) { @@ -539,8 +513,8 @@ mapped_id_start_ + 3, false); CreateAndCheckMouseEvent(WebPointerProperties::PointerType::kUnknown, 2, mapped_id_start_ + 2, false); - CreateAndCheckTouchCancel(WebPointerProperties::PointerType::kUnknown, 3, - mapped_id_start_ + 3, false); + CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kUnknown, 3, + mapped_id_start_ + 3, false); pointer_event_factory_.Remove(pointer_event1->pointerId()); @@ -560,8 +534,8 @@ CreateAndCheckTouchEvent(WebPointerProperties::PointerType::kMouse, i, expected_mouse_id_, true); } - CreateAndCheckTouchCancel(WebPointerProperties::PointerType::kMouse, 0, - expected_mouse_id_, true); + CreateAndCheckPointerCancel(WebPointerProperties::PointerType::kMouse, 0, + expected_mouse_id_, true); } TEST_F(PointerEventFactoryTest, CoalescedEvents) {
diff --git a/third_party/WebKit/Source/core/input/EventHandler.cpp b/third_party/WebKit/Source/core/input/EventHandler.cpp index e5409b7b..ba6e1cd 100644 --- a/third_party/WebKit/Source/core/input/EventHandler.cpp +++ b/third_party/WebKit/Source/core/input/EventHandler.cpp
@@ -550,9 +550,8 @@ } WebInputEventResult EventHandler::HandlePointerEvent( - const WebPointerEvent& web_pointer_event, - Node* target) { - return pointer_event_manager_->HandlePointerEvent(web_pointer_event, target); + const WebPointerEvent& web_pointer_event) { + return pointer_event_manager_->HandlePointerEvent(web_pointer_event); } WebInputEventResult EventHandler::HandleMousePressEvent(
diff --git a/third_party/WebKit/Source/core/input/EventHandler.h b/third_party/WebKit/Source/core/input/EventHandler.h index b6a8ccbf..e4b61d9 100644 --- a/third_party/WebKit/Source/core/input/EventHandler.h +++ b/third_party/WebKit/Source/core/input/EventHandler.h
@@ -148,7 +148,7 @@ const Vector<WebMouseEvent>& coalesced_events); void HandleMouseLeaveEvent(const WebMouseEvent&); - WebInputEventResult HandlePointerEvent(const WebPointerEvent&, Node* target); + WebInputEventResult HandlePointerEvent(const WebPointerEvent&); WebInputEventResult HandleMousePressEvent(const WebMouseEvent&); WebInputEventResult HandleMouseReleaseEvent(const WebMouseEvent&);
diff --git a/third_party/WebKit/Source/core/input/MouseEventManager.cpp b/third_party/WebKit/Source/core/input/MouseEventManager.cpp index 8d4cd13..a9f15b4 100644 --- a/third_party/WebKit/Source/core/input/MouseEventManager.cpp +++ b/third_party/WebKit/Source/core/input/MouseEventManager.cpp
@@ -913,8 +913,7 @@ // corresponding pointer. if (initiator == DragInitiator::kMouse) { frame_->GetEventHandler().HandlePointerEvent( - WebPointerEvent(WebInputEvent::Type::kPointerCancel, event.Event()), - event.InnerNode()); + WebPointerEvent(WebInputEvent::Type::kPointerCancel, event.Event())); } // TODO(crbug.com/708278): If the drag starts with touch the touch cancel // should trigger the release of pointer capture.
diff --git a/third_party/WebKit/Source/core/input/PointerEventManager.cpp b/third_party/WebKit/Source/core/input/PointerEventManager.cpp index 8d81dbfe..4215654f 100644 --- a/third_party/WebKit/Source/core/input/PointerEventManager.cpp +++ b/third_party/WebKit/Source/core/input/PointerEventManager.cpp
@@ -80,7 +80,7 @@ for (auto& entry : prevent_mouse_event_for_pointer_type_) entry = false; touch_event_manager_->Clear(); - in_canceled_state_for_pointer_type_touch_ = false; + scroll_capable_pointers_canceled_ = false; pointer_event_factory_.Clear(); touch_ids_for_canceled_pointerdowns_.clear(); node_under_pointer_.clear(); @@ -257,53 +257,81 @@ } } -void PointerEventManager::BlockTouchPointers(TimeTicks platform_time_stamp) { - if (in_canceled_state_for_pointer_type_touch_) - return; - in_canceled_state_for_pointer_type_touch_ = true; +void PointerEventManager::DispatchPointerCancelEvents( + const WebPointerEvent& web_pointer_event) { + DCHECK(web_pointer_event.GetType() == WebInputEvent::Type::kPointerCancel); - Vector<int> touch_pointer_ids = - pointer_event_factory_.GetPointerIdsOfScrollCapablePointers(); - - for (int pointer_id : touch_pointer_ids) { - PointerEvent* pointer_event = + HeapVector<Member<PointerEvent>> canceled_pointer_events; + if (web_pointer_event.pointer_type == + WebPointerProperties::PointerType::kMouse) { + canceled_pointer_events.push_back( pointer_event_factory_.CreatePointerCancelEvent( - pointer_id, WebPointerProperties::PointerType::kTouch, - platform_time_stamp); + PointerEventFactory::kMouseId, + TimeTicks::FromSeconds(web_pointer_event.TimeStampSeconds()))); + } else { + // TODO(nzolghadr): Maybe canceling all the scroll capable pointers is not + // the best strategy here. See the github issue for more details: + // https://github.com/w3c/pointerevents/issues/226 - DCHECK(node_under_pointer_.Contains(pointer_id)); - EventTarget* target = node_under_pointer_.at(pointer_id).target; + // Cancel all scroll capable pointers if the pointer is not mouse. + if (!scroll_capable_pointers_canceled_) { + Vector<int> scroll_capable_pointer_ids = + pointer_event_factory_.GetPointerIdsOfScrollCapablePointers(); - ProcessCaptureAndPositionOfPointerEvent(pointer_event, target); + for (int pointer_id : scroll_capable_pointer_ids) { + canceled_pointer_events.push_back( + pointer_event_factory_.CreatePointerCancelEvent( + pointer_id, + TimeTicks::FromSeconds(web_pointer_event.TimeStampSeconds()))); + } - // TODO(nzolghadr): This event follows implicit TE capture. The actual - // target would depend on PE capturing. Perhaps need to split TE/PE event - // path upstream? crbug.com/579553. + scroll_capable_pointers_canceled_ = true; + } + } + + for (auto pointer_event : canceled_pointer_events) { + // If we are sending a pointercancel we have sent the pointerevent to some + // target before. + DCHECK(node_under_pointer_.Contains(pointer_event->pointerId())); + EventTarget* target = + node_under_pointer_.at(pointer_event->pointerId()).target; + DispatchPointerEvent( GetEffectiveTargetForPointerEvent(target, pointer_event->pointerId()), pointer_event); ReleasePointerCapture(pointer_event->pointerId()); - // Sending the leave/out events and lostpointercapture - // because the next touch event will have a different id. So delayed - // sending of lostpointercapture won't work here. - ProcessCaptureAndPositionOfPointerEvent(pointer_event, nullptr); + // Send the leave/out events and lostpointercapture if needed. + // Note that for mouse due to the web compat we still don't send the + // boundary events and for now only send lostpointercapture if needed. + // Sending boundary events and possibly updating hover for mouse + // in this case may cause some of the existing pages to break. + if (web_pointer_event.pointer_type == + WebPointerProperties::PointerType::kMouse) { + ProcessPendingPointerCapture(pointer_event); + } else { + ProcessCaptureAndPositionOfPointerEvent(pointer_event, nullptr); + } RemovePointer(pointer_event); } } void PointerEventManager::UnblockTouchPointers() { - in_canceled_state_for_pointer_type_touch_ = false; + scroll_capable_pointers_canceled_ = false; } WebInputEventResult PointerEventManager::HandleTouchEvents( const WebTouchEvent& event, const Vector<WebTouchEvent>& coalesced_events) { if (event.GetType() == WebInputEvent::kTouchScrollStarted) { - BlockTouchPointers(TimeTicks::FromSeconds(event.TimeStampSeconds())); - return WebInputEventResult::kHandledSystem; + WebPointerEvent web_pointer_event_cancel; + web_pointer_event_cancel.SetType(WebInputEvent::Type::kPointerCancel); + web_pointer_event_cancel.SetTimeStampSeconds(event.TimeStampSeconds()); + web_pointer_event_cancel.pointer_type = + WebPointerProperties::PointerType::kTouch; + return HandlePointerEvent(web_pointer_event_cancel); } bool new_touch_sequence = true; @@ -333,7 +361,7 @@ // associated with so just pick the first finger. std::unique_ptr<UserGestureIndicator> holder; if (event.GetType() == WebInputEvent::kTouchEnd && - !in_canceled_state_for_pointer_type_touch_ && event.touches_length && + !scroll_capable_pointers_canceled_ && event.touches_length && first_pointer_event_target.target_frame) { holder = Frame::NotifyUserActivation(first_pointer_event_target.target_frame); @@ -432,7 +460,7 @@ // required. // Do not send pointer events for stationary touches or null targetFrame if (pointer_event_target.target_node && pointer_event_target.target_frame && - !in_canceled_state_for_pointer_type_touch_) { + !scroll_capable_pointers_canceled_) { PointerEvent* pointer_event = pointer_event_factory_.Create( touch_point, coalesced_events, static_cast<WebInputEvent::Modifiers>(modifiers), @@ -461,7 +489,7 @@ WebInputEventResult PointerEventManager::SendTouchPointerEvent( EventTarget* target, PointerEvent* pointer_event) { - if (in_canceled_state_for_pointer_type_touch_) + if (scroll_capable_pointers_canceled_) return WebInputEventResult::kNotHandled; ProcessCaptureAndPositionOfPointerEvent(pointer_event, target); @@ -489,29 +517,16 @@ } WebInputEventResult PointerEventManager::HandlePointerEvent( - const WebPointerEvent& web_pointer_event, - Node* target) { + const WebPointerEvent& web_pointer_event) { // TODO(crbug.com/625841): This function only handles pointercancel for now. // But we should extend it to handle any pointerevents. DCHECK(web_pointer_event.GetType() == WebInputEvent::Type::kPointerCancel); - PointerEvent* pointer_event = - pointer_event_factory_.CreatePointerCancelEvent(web_pointer_event); - EventTarget* effective_target = - GetEffectiveTargetForPointerEvent(target, pointer_event->pointerId()); - WebInputEventResult result = - DispatchPointerEvent(effective_target, pointer_event); + if (web_pointer_event.GetType() == WebInputEvent::Type::kPointerCancel) { + DispatchPointerCancelEvents(web_pointer_event); + } - ReleasePointerCapture(pointer_event->pointerId()); - - // TODO(nzolghadr): Instead of |ProcessPendingPointerCapture| maybe we - // should have used ProcessCaptureAndPositionOfPointerEvent but that might - // be sending boundary events however we probably not want that all the - // time. - ProcessPendingPointerCapture(pointer_event); - - RemovePointer(pointer_event); - return result; + return WebInputEventResult::kHandledSystem; } WebInputEventResult PointerEventManager::SendMousePointerEvent(
diff --git a/third_party/WebKit/Source/core/input/PointerEventManager.h b/third_party/WebKit/Source/core/input/PointerEventManager.h index ae38ff4..47051df 100644 --- a/third_party/WebKit/Source/core/input/PointerEventManager.h +++ b/third_party/WebKit/Source/core/input/PointerEventManager.h
@@ -34,7 +34,7 @@ // cause firing DOM pointerevents, mouseevent, and touch events accordingly. // TODO(crbug.com/625841): We need to get all event handling path to go // through this function. - WebInputEventResult HandlePointerEvent(const WebPointerEvent&, Node* target); + WebInputEventResult HandlePointerEvent(const WebPointerEvent&); // Sends the mouse pointer events and the boundary events // that it may cause. It also sends the compat mouse events @@ -137,11 +137,10 @@ Member<PointerEvent> pointer_event_; }; - // Inhibits firing of touch-type PointerEvents until unblocked by - // unblockTouchPointers(). Also sends pointercancels for existing touch-type - // PointerEvents. See: - // www.w3.org/TR/pointerevents/#declaring-candidate-regions-for-default-touch-behaviors - void BlockTouchPointers(TimeTicks platform_time_stamp); + // Sends pointercancels for existing PointerEvents. For example when browser + // starts dragging with mouse or when we start scrolling with scroll capable + // pointers pointercancel events should be dispatched. + void DispatchPointerCancelEvents(const WebPointerEvent&); // Enables firing of touch-type PointerEvents after they were inhibited by // blockTouchPointers(). @@ -212,9 +211,9 @@ bool prevent_mouse_event_for_pointer_type_ [static_cast<size_t>(WebPointerProperties::PointerType::kLastEntry) + 1]; - // Set upon TouchScrollStarted when sending a pointercancel, prevents PE - // dispatches for touches until all touch-points become inactive. - bool in_canceled_state_for_pointer_type_touch_; + // Set upon scrolling starts when sending a pointercancel, prevents PE + // dispatches for scroll capable pointers until all of them become inactive. + bool scroll_capable_pointers_canceled_; Deque<uint32_t> touch_ids_for_canceled_pointerdowns_;
diff --git a/third_party/WebKit/Source/core/input/PointerEventManagerTest.cpp b/third_party/WebKit/Source/core/input/PointerEventManagerTest.cpp new file mode 100644 index 0000000..8bb5db0b --- /dev/null +++ b/third_party/WebKit/Source/core/input/PointerEventManagerTest.cpp
@@ -0,0 +1,124 @@ +// 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 "core/dom/Document.h" +#include "core/dom/events/EventListener.h" +#include "core/html/HTMLElement.h" +#include "core/input/EventHandler.h" +#include "core/input/PointerEventManager.h" +#include "core/testing/sim/SimRequest.h" +#include "core/testing/sim/SimTest.h" + +namespace blink { + +namespace { +class CheckPointerEventListenerCallback final : public EventListener { + public: + static CheckPointerEventListenerCallback* Create() { + return new CheckPointerEventListenerCallback(); + } + + bool operator==(const EventListener& other) const override { + return this == &other; + } + + void handleEvent(ExecutionContext*, Event* event) override { + const String pointer_type = ((PointerEvent*)event)->pointerType(); + if (pointer_type == "mouse") + mouse_event_received_count_++; + else if (pointer_type == "touch") + touch_event_received_count_++; + else if (pointer_type == "pen") + pen_event_received_count_++; + } + + int mouseEventCount() const { return mouse_event_received_count_; } + int touchEventCount() const { return touch_event_received_count_; } + int penEventCount() const { return pen_event_received_count_; } + + private: + CheckPointerEventListenerCallback() + : EventListener(EventListener::kCPPEventListenerType) {} + int mouse_event_received_count_ = 0; + int touch_event_received_count_ = 0; + int pen_event_received_count_ = 0; +}; + +} // namespace + +class PointerEventManagerTest : public SimTest { + protected: + EventHandler& EventHandler() { + return GetDocument().GetFrame()->GetEventHandler(); + } +}; + +TEST_F(PointerEventManagerTest, PointerCancelsOfAllTypes) { + WebView().Resize(WebSize(400, 400)); + SimRequest request("https://example.com/test.html", "text/html"); + LoadURL("https://example.com/test.html"); + request.Complete( + "<body style='padding: 0px; width: 400px; height: 400px;'>" + "<div draggable='true' style='width: 150px; height: 150px;'></div>" + "</body>"); + CheckPointerEventListenerCallback* callback = + CheckPointerEventListenerCallback::Create(); + GetDocument().body()->addEventListener(EventTypeNames::pointercancel, + callback); + + WebTouchEvent event; + event.SetFrameScale(1); + WebTouchPoint point( + WebPointerProperties(1, WebPointerProperties::PointerType::kTouch, + WebPointerProperties::Button::kLeft, + WebFloatPoint(100, 100), WebFloatPoint(100, 100))); + point.state = WebTouchPoint::State::kStatePressed; + event.touches[event.touches_length++] = point; + event.SetType(WebInputEvent::kTouchStart); + EventHandler().HandleTouchEvent(event, Vector<WebTouchEvent>()); + + point.pointer_type = WebPointerProperties::PointerType::kPen; + event.touches[0] = point; + event.SetType(WebInputEvent::kTouchStart); + EventHandler().HandleTouchEvent(event, Vector<WebTouchEvent>()); + + WebMouseEvent mouse_down_event( + WebInputEvent::kMouseDown, WebFloatPoint(100, 100), + WebFloatPoint(100, 100), WebPointerProperties::Button::kLeft, 0, 0, 0); + mouse_down_event.SetFrameScale(1); + EventHandler().HandleMousePressEvent(mouse_down_event); + + ASSERT_EQ(callback->mouseEventCount(), 0); + ASSERT_EQ(callback->touchEventCount(), 0); + ASSERT_EQ(callback->penEventCount(), 0); + + point.pointer_type = WebPointerProperties::PointerType::kPen; + event.touches[0] = point; + event.SetType(WebInputEvent::kTouchScrollStarted); + EventHandler().HandleTouchEvent(event, Vector<WebTouchEvent>()); + ASSERT_EQ(callback->mouseEventCount(), 0); + ASSERT_EQ(callback->touchEventCount(), 1); + ASSERT_EQ(callback->penEventCount(), 1); + + point.pointer_type = WebPointerProperties::PointerType::kTouch; + event.touches[0] = point; + event.SetType(WebInputEvent::kTouchScrollStarted); + EventHandler().HandleTouchEvent(event, Vector<WebTouchEvent>()); + ASSERT_EQ(callback->mouseEventCount(), 0); + ASSERT_EQ(callback->touchEventCount(), 1); + ASSERT_EQ(callback->penEventCount(), 1); + + WebMouseEvent mouse_move_event( + WebInputEvent::kMouseMove, WebFloatPoint(200, 200), + WebFloatPoint(200, 200), WebPointerProperties::Button::kLeft, 0, 0, 0); + mouse_move_event.SetFrameScale(1); + EventHandler().HandleMouseMoveEvent(mouse_move_event, + Vector<WebMouseEvent>()); + + ASSERT_EQ(callback->mouseEventCount(), 1); + ASSERT_EQ(callback->touchEventCount(), 1); + ASSERT_EQ(callback->penEventCount(), 1); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/shapes/Shape.cpp b/third_party/WebKit/Source/core/layout/shapes/Shape.cpp index 26c8a05c..f0c1e267c 100644 --- a/third_party/WebKit/Source/core/layout/shapes/Shape.cpp +++ b/third_party/WebKit/Source/core/layout/shapes/Shape.cpp
@@ -256,8 +256,10 @@ Image::kDoNotClampImageToSourceRect, Image::kSyncDecode); WTF::ArrayBufferContents contents; - image_buffer->GetImageData(IntRect(IntPoint(), image_rect.Size()), - contents); + bool image_data_exists = image_buffer->GetImageData( + IntRect(IntPoint(), image_rect.Size()), contents); + if (!image_data_exists) + return nullptr; DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(contents); DOMUint8ClampedArray* pixel_array = DOMUint8ClampedArray::Create( array_buffer, 0, array_buffer->ByteLength());
diff --git a/third_party/WebKit/Source/core/layout/shapes/ShapeOutsideInfo.cpp b/third_party/WebKit/Source/core/layout/shapes/ShapeOutsideInfo.cpp index 8c0ea04..22c655df 100644 --- a/third_party/WebKit/Source/core/layout/shapes/ShapeOutsideInfo.cpp +++ b/third_party/WebKit/Source/core/layout/shapes/ShapeOutsideInfo.cpp
@@ -172,9 +172,16 @@ layout_box_, layout_box_.GetDocument(), layout_box_.StyleRef(), FlooredIntSize(image_size), nullptr); - return Shape::CreateRasterShape(image.get(), shape_image_threshold, - image_rect, margin_rect, writing_mode, - margin); + std::unique_ptr<Shape> new_shape = + Shape::CreateRasterShape(image.get(), shape_image_threshold, image_rect, + margin_rect, writing_mode, margin); + if (!new_shape) { + layout_box_.GetDocument().AddConsoleMessage( + ConsoleMessage::Create(kRenderingMessageSource, kErrorMessageLevel, + "The shape-outside image is too large.")); + return Shape::CreateEmptyRasterShape(writing_mode, margin); + } + return new_shape; } const Shape& ShapeOutsideInfo::ComputedShape() const {
diff --git a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp index dec9af58..0c42618 100644 --- a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp +++ b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp
@@ -227,35 +227,38 @@ } void BoxPaintInvalidator::InvalidateScrollingContentsBackground( - BackgroundInvalidationType backgroundInvalidationType) { + BackgroundInvalidationType background_invalidation_type) { if (!BackgroundPaintsOntoScrollingContentsLayer()) return; - if (backgroundInvalidationType == BackgroundInvalidationType::kNone) + if (background_invalidation_type == BackgroundInvalidationType::kNone) return; - // TODO(crbug.com/732611): Implement raster invalidation of background on - // scrolling contents layer for SPv175. - if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) { + PaintInvalidationReason reason; + if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) { + reason = background_invalidation_type == BackgroundInvalidationType::kFull + ? PaintInvalidationReason::kBackgroundOnScrollingContentsLayer + : PaintInvalidationReason::kIncremental; + } else { + // For SPv1 we need this reason for both full and incremental invalidation + // to let ObjectPaintInvalidator::SetBackingNeedsPaintInvalidationInRect() + // know we are invalidating on the scrolling contents backing. + reason = PaintInvalidationReason::kBackgroundOnScrollingContentsLayer; const LayoutRect& old_layout_overflow = box_.PreviousLayoutOverflowRect(); LayoutRect new_layout_overflow = box_.LayoutOverflowRect(); - if (backgroundInvalidationType == BackgroundInvalidationType::kFull) { + if (background_invalidation_type == BackgroundInvalidationType::kFull) { ObjectPaintInvalidatorWithContext(box_, context_) - .FullyInvalidatePaint( - PaintInvalidationReason::kBackgroundOnScrollingContentsLayer, - old_layout_overflow, new_layout_overflow); + .FullyInvalidatePaint(reason, old_layout_overflow, + new_layout_overflow); } else { - IncrementallyInvalidatePaint( - PaintInvalidationReason::kBackgroundOnScrollingContentsLayer, - old_layout_overflow, new_layout_overflow); + IncrementallyInvalidatePaint(reason, old_layout_overflow, + new_layout_overflow); } } context_.painting_layer->SetNeedsRepaint(); - // Currently we use CompositedLayerMapping as the DisplayItemClient to paint - // background on the scrolling contents layer. ObjectPaintInvalidator(box_).InvalidateDisplayItemClient( *box_.Layer()->GetCompositedLayerMapping()->ScrollingContentsLayer(), - PaintInvalidationReason::kBackgroundOnScrollingContentsLayer); + reason); } PaintInvalidationReason BoxPaintInvalidator::InvalidatePaint() {
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index 5776c3d8..8e5a18b 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1683,6 +1683,7 @@ "//components/viz/test:test_support", "//testing/gmock", "//testing/gtest:gtest", + "//testing/perf", ] deps = [ @@ -1959,6 +1960,7 @@ "testing/BlinkPerfTestSuite.cpp", "testing/BlinkPerfTestSuite.h", "testing/RunAllPerfTests.cpp", + "testing/ShapingLineBreakerPerfTest.cpp", ] configs += [ @@ -1975,6 +1977,7 @@ "//base/test:test_support", "//testing/gtest", "//testing/perf", + "//third_party:freetype_harfbuzz", "//third_party/WebKit/Source/platform/scheduler:perf_tests", ] }
diff --git a/third_party/WebKit/Source/platform/testing/DEPS b/third_party/WebKit/Source/platform/testing/DEPS index 8993c42d8..34e99e32 100644 --- a/third_party/WebKit/Source/platform/testing/DEPS +++ b/third_party/WebKit/Source/platform/testing/DEPS
@@ -14,4 +14,5 @@ "+cc", "+components/viz/test", "+mojo/edk/embedder", + '+testing', ]
diff --git a/third_party/WebKit/Source/platform/testing/ShapingLineBreakerPerfTest.cpp b/third_party/WebKit/Source/platform/testing/ShapingLineBreakerPerfTest.cpp new file mode 100644 index 0000000..46981fba --- /dev/null +++ b/third_party/WebKit/Source/platform/testing/ShapingLineBreakerPerfTest.cpp
@@ -0,0 +1,147 @@ +// 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 "platform/fonts/shaping/ShapingLineBreaker.h" + +#include <unicode/uscript.h> +#include "base/time/time.h" +#include "cc/base/lap_timer.h" +#include "platform/fonts/Font.h" +#include "platform/fonts/FontCache.h" +#include "platform/fonts/FontTestUtilities.h" +#include "platform/fonts/shaping/ShapeResultInlineHeaders.h" +#include "platform/fonts/shaping/ShapeResultTestInfo.h" +#include "platform/text/TextBreakIterator.h" +#include "platform/text/TextRun.h" +#include "platform/wtf/Vector.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/perf/perf_test.h" + +namespace blink { +namespace { + +static const int kTimeLimitMillis = 2000; +static const int kWarmupRuns = 5; +static const int kTimeCheckInterval = 10; + +LayoutUnit ShapeText(ShapingLineBreaker* breaker, + LayoutUnit available_space, + unsigned string_length) { + unsigned break_offset = 0; + LayoutUnit total_width; + ShapingLineBreaker::Result result; + RefPtr<ShapeResult> shape_result; + while (break_offset < string_length) { + shape_result = breaker->ShapeLine(break_offset, available_space, &result); + break_offset = result.break_offset; + total_width += shape_result->SnappedWidth(); + } + return total_width; +} + +} // anonymous namespace + +class ShapingLineBreakerPerfTest : public ::testing::Test { + public: + ShapingLineBreakerPerfTest() + : timer_(kWarmupRuns, + base::TimeDelta::FromMilliseconds(kTimeLimitMillis), + kTimeCheckInterval) {} + + void SetUp() override { + font_description.SetComputedSize(12.0); + font = Font(font_description); + font.Update(nullptr); + } + + void TearDown() override {} + + FontCachePurgePreventer font_cache_purge_preventer; + FontDescription font_description; + Font font; + unsigned start_index = 0; + unsigned num_glyphs = 0; + hb_script_t script = HB_SCRIPT_INVALID; + cc::LapTimer timer_; +}; + +TEST_F(ShapingLineBreakerPerfTest, ShapeLatinText) { + // "My Brother's Keeper?" + // By William Arthur Dunkerley (John Oxenham) + // In the public domain. + String string( + u"\"Am I my brother's keeper?\"" + "Yes, of a truth!" + "Thine asking is thine answer." + "That self-condemning cry of Cain" + "Has been the plea of every selfish soul since then," + "Which hath its brother slain." + "God's word is plain," + "And doth thy shrinking soul arraign." + "" + "Thy brother's keeper?" + "Yea, of a truth thou art!" + "For if not--who?" + "Are ye not both,--both thou and he" + "Of God's great family?" + "How rid thee of thy soul's responsibility?" + "For every ill in all the world" + "Each soul is sponsor and account must bear." + "And He, and he thy brother of despair," + "Claim, of thy overmuch, their share." + "" + "Thou hast had good, and he the strangled days;" + "But now,--the old things pass." + "No longer of thy grace" + "Is he content to live in evil case" + "For the anointing of thy shining face." + "The old things pass.--Beware lest ye pass with them," + "And your place" + "Become an emptiness!" + "" + "Beware! Lest, when the \"Have-nots\" claim," + "From those who have, their rightful share," + "Thy borders be swept bare" + "As by the final flame." + "Better to share before than after." + "\"After?\" ... For thee may be no after!" + "Only the howl of mocking laughter" + "At thy belated care. Make no mistake!--" + "\"After\" will be too late." + "When once the \"Have-nots\" claim ... they take." + "\"After!\" ... When that full claim is made," + "You and your golden gods may all lie dead." + "" + "Set now your house in order," + "Ere it be too late!" + "For, once the storm of hate" + "Be loosed, no man shall stay it till" + "Its thirst has slaked its fill," + "And you, poor victims of this last \"too late,\"" + "Shall in the shadows mourn your lost estate."); + unsigned len = string.length(); + LazyLineBreakIterator break_iterator(string, "en-US", LineBreakType::kNormal); + TextDirection direction = TextDirection::kLtr; + + HarfBuzzShaper shaper(string.Characters16(), len); + RefPtr<ShapeResult> result = shaper.Shape(&font, direction); + ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + + RefPtr<ShapeResult> line; + LayoutUnit available_width_px(500); + + LayoutUnit expected_width = ShapeText(&breaker, available_width_px, len); + timer_.Reset(); + do { + LayoutUnit width = ShapeText(&breaker, available_width_px, len); + EXPECT_EQ(expected_width, width); + timer_.NextLap(); + } while (!timer_.HasTimeLimitExpired()); + + perf_test::PrintResult("ShapingLineBreakerPerfTest", "shape latin text", "", + timer_.LapsPerSecond(), "runs/s", true); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/testing/data/third_party/Amiri/README b/third_party/WebKit/Source/platform/testing/data/third_party/Amiri/README new file mode 100644 index 0000000..a7071c1 --- /dev/null +++ b/third_party/WebKit/Source/platform/testing/data/third_party/Amiri/README
@@ -0,0 +1,90 @@ +Amiri is a classical Arabic typeface in Naskh style for typesetting books and other running text. Its design is a revival of the beautiful typeface pioneered in early 20th century by Bulaq Press in Cairo, also known as Amiria Press, after which the font is named. +Read more about the project at www.amirifont.org +Updated in July 2017 to v0.109 + +SIL OPEN FONT LICENSE + +Version 1.1 - 26 February 2007 + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting — in part or in whole — any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file
diff --git a/third_party/WebKit/Source/platform/testing/data/third_party/Amiri/amiri_arabic.woff2 b/third_party/WebKit/Source/platform/testing/data/third_party/Amiri/amiri_arabic.woff2 new file mode 100644 index 0000000..da20321 --- /dev/null +++ b/third_party/WebKit/Source/platform/testing/data/third_party/Amiri/amiri_arabic.woff2 Binary files differ
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index 6eede7f..c3d0da1 100644 --- a/third_party/crashpad/README.chromium +++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@ Short Name: crashpad URL: https://crashpad.chromium.org/ Version: unknown -Revision: 3fae8ff07c097da6d0042510bdbe5b16c67a8e12 +Revision: 6950a552bfab43f05d6644811271f8f5c3b91c20 License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes
diff --git a/third_party/crashpad/crashpad/client/annotation.h b/third_party/crashpad/crashpad/client/annotation.h index 141aa12..f76ddf68 100644 --- a/third_party/crashpad/crashpad/client/annotation.h +++ b/third_party/crashpad/crashpad/client/annotation.h
@@ -67,10 +67,10 @@ //! are permanently referenced by a global object. class Annotation { public: - //! \brief The maximum length of the #name field in bytes. + //! \brief The maximum length of an annotation’s name, in bytes. static constexpr size_t kNameMaxLength = 64; - //! \brief The maximum size of the #value field in bytes. + //! \brief The maximum size of an annotation’s value, in bytes. static constexpr size_t kValueMaxSize = 2048; //! \brief The type used for \a SetSize().
diff --git a/third_party/crashpad/crashpad/client/crashpad_info.h b/third_party/crashpad/crashpad/client/crashpad_info.h index 7ce55ed..fc391bf 100644 --- a/third_party/crashpad/crashpad/client/crashpad_info.h +++ b/third_party/crashpad/crashpad/client/crashpad_info.h
@@ -116,15 +116,15 @@ //! typed data and it is not limited to a dictionary form. Annotations are //! interpreted by Crashpad as module-level annotations. //! - //! Annotations may exist in \a annotations_list at the time that this - //! method is called, or they may be added, removed, or modified in \a - //! annotations_list after this method is called. + //! Annotations may exist in \a list at the time that this method is called, + //! or they may be added, removed, or modified in \a list after this method is + //! called. //! - //! \param[in] annotations_list A list of set Annotation objects that maintain - //! arbitrary, typed key-value state. The CrashpadInfo object does not - //! take ownership of the AnnotationsList object. It is the caller’s - //! responsibility to ensure that this pointer remains valid while it is - //! in effect for a CrashpadInfo object. + //! \param[in] list A list of set Annotation objects that maintain arbitrary, + //! typed key-value state. The CrashpadInfo object does not take ownership + //! of the AnnotationsList object. It is the caller’s responsibility to + //! ensure that this pointer remains valid while it is in effect for a + //! CrashpadInfo object. //! //! \sa annotations_list() //! \sa AnnotationList::Register()
diff --git a/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc b/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc index 1534443..65fed90f 100644 --- a/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc +++ b/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc
@@ -37,8 +37,8 @@ constexpr DWORD kExpectedExitCode = 0x1CEB00DA; void StartAndCrashWithExtendedHandler(const base::FilePath& temp_dir) { - base::FilePath handler_path = TestPaths::Executable().DirName().Append( - FILE_PATH_LITERAL("crashpad_handler_test_extended_handler.exe")); + base::FilePath handler_path = TestPaths::BuildArtifact( + L"handler", L"extended_handler", TestPaths::FileType::kExecutable); CrashpadClient client; ASSERT_TRUE(client.StartHandler(handler_path,
diff --git a/third_party/crashpad/crashpad/handler/main.cc b/third_party/crashpad/crashpad/handler/main.cc index bc4ab99b..c0a04f40 100644 --- a/third_party/crashpad/crashpad/handler/main.cc +++ b/third_party/crashpad/crashpad/handler/main.cc
@@ -22,10 +22,13 @@ #endif #if defined(OS_MACOSX) + int main(int argc, char* argv[]) { return crashpad::HandlerMain(argc, argv, nullptr); } + #elif defined(OS_WIN) + namespace { int HandlerMainAdaptor(int argc, char* argv[]) { @@ -34,7 +37,17 @@ } // namespace +// The default entry point for /subsystem:windows. In Crashpad’s own build, this +// is used by crashpad_handler.exe. It’s also used by crashpad_handler.com when +// produced by editbin from a copy of crashpad_handler.exe. int APIENTRY wWinMain(HINSTANCE, HINSTANCE, wchar_t*, int) { return crashpad::ToolSupport::Wmain(__argc, __wargv, HandlerMainAdaptor); } + +// The default entry point for /subsystem:console. This is not currently used by +// Crashpad’s own build, but may be used by other builds. +int wmain(int argc, wchar_t* argv[]) { + return crashpad::ToolSupport::Wmain(argc, argv, HandlerMainAdaptor); +} + #endif // OS_MACOSX
diff --git a/third_party/crashpad/crashpad/handler/win/crash_other_program.cc b/third_party/crashpad/crashpad/handler/win/crash_other_program.cc index 93a3a07..ddad4c53 100644 --- a/third_party/crashpad/crashpad/handler/win/crash_other_program.cc +++ b/third_party/crashpad/crashpad/handler/win/crash_other_program.cc
@@ -90,8 +90,8 @@ // Launch another process that hangs. base::FilePath test_executable = TestPaths::Executable(); - std::wstring child_test_executable = - test_executable.DirName().Append(L"hanging_program.exe").value(); + base::FilePath child_test_executable = + test_executable.DirName().Append(L"hanging_program.exe"); ChildLauncher child(child_test_executable, argv[1]); child.Start(); if (testing::Test::HasFatalFailure()) {
diff --git a/third_party/crashpad/crashpad/minidump/minidump.gyp b/third_party/crashpad/crashpad/minidump/minidump.gyp index 3135de3d..e36006c 100644 --- a/third_party/crashpad/crashpad/minidump/minidump.gyp +++ b/third_party/crashpad/crashpad/minidump/minidump.gyp
@@ -33,6 +33,8 @@ '..', ], 'sources': [ + 'minidump_byte_array_writer.cc', + 'minidump_byte_array_writer.h', 'minidump_context.h', 'minidump_context_writer.cc', 'minidump_context_writer.h',
diff --git a/third_party/crashpad/crashpad/minidump/minidump_byte_array_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_byte_array_writer.cc new file mode 100644 index 0000000..05b698db --- /dev/null +++ b/third_party/crashpad/crashpad/minidump/minidump_byte_array_writer.cc
@@ -0,0 +1,73 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "minidump/minidump_byte_array_writer.h" + +#include "base/logging.h" +#include "util/file/file_writer.h" +#include "util/numeric/safe_assignment.h" + +namespace crashpad { + +MinidumpByteArrayWriter::MinidumpByteArrayWriter() + : minidump_array_(new MinidumpByteArray()) {} + +MinidumpByteArrayWriter::~MinidumpByteArrayWriter() = default; + +void MinidumpByteArrayWriter::set_data(const uint8_t* data, size_t size) { + data_.clear(); + data_.insert(data_.begin(), data, data + size); +} + +bool MinidumpByteArrayWriter::Freeze() { + DCHECK_EQ(state(), kStateMutable); + + if (!MinidumpWritable::Freeze()) { + return false; + } + + size_t size = data_.size(); + if (!AssignIfInRange(&minidump_array_->length, size)) { + LOG(ERROR) << "data size " << size << " is out of range"; + return false; + } + + return true; +} + +size_t MinidumpByteArrayWriter::SizeOfObject() { + DCHECK_EQ(state(), kStateFrozen); + + return sizeof(*minidump_array_) + data_.size(); +} + +bool MinidumpByteArrayWriter::WriteObject(FileWriterInterface* file_writer) { + DCHECK_EQ(state(), kStateWritable); + + WritableIoVec iov; + iov.iov_base = minidump_array_.get(); + iov.iov_len = sizeof(*minidump_array_); + + std::vector<WritableIoVec> iovecs(1, iov); + + if (!data_.empty()) { + iov.iov_base = data_.data(); + iov.iov_len = data_.size(); + iovecs.push_back(iov); + } + + return file_writer->WriteIoVec(&iovecs); +} + +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/minidump/minidump_byte_array_writer.h b/third_party/crashpad/crashpad/minidump/minidump_byte_array_writer.h new file mode 100644 index 0000000..c399f03 --- /dev/null +++ b/third_party/crashpad/crashpad/minidump/minidump_byte_array_writer.h
@@ -0,0 +1,65 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_MINIDUMP_MINIDUMP_BYTE_ARRAY_WRITER_H_ +#define CRASHPAD_MINIDUMP_MINIDUMP_BYTE_ARRAY_WRITER_H_ + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "minidump/minidump_extensions.h" +#include "minidump/minidump_writable.h" + +namespace crashpad { + +//! \brief Writes a variable-length byte array for a minidump into a +//! \sa MinidumpByteArray. +class MinidumpByteArrayWriter final : public internal::MinidumpWritable { + public: + MinidumpByteArrayWriter(); + ~MinidumpByteArrayWriter() override; + + //! \brief Sets the data to be written. + //! + //! \note Valid in #kStateMutable. + void set_data(const std::vector<uint8_t>& data) { data_ = data; } + + //! \brief Sets the data to be written. + //! + //! \note Valid in #kStateMutable. + void set_data(const uint8_t* data, size_t size); + + //! \brief Gets the data to be written. + //! + //! \note Valid in any state. + const std::vector<uint8_t>& data() const { return data_; } + + protected: + // MinidumpWritable: + + bool Freeze() override; + size_t SizeOfObject() override; + bool WriteObject(FileWriterInterface* file_writer) override; + + private: + std::unique_ptr<MinidumpByteArray> minidump_array_; + std::vector<uint8_t> data_; + + DISALLOW_COPY_AND_ASSIGN(MinidumpByteArrayWriter); +}; + +} // namespace crashpad + +#endif // CRASHPAD_MINIDUMP_MINIDUMP_BYTE_ARRAY_WRITER_H_
diff --git a/third_party/crashpad/crashpad/minidump/minidump_byte_array_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_byte_array_writer_test.cc new file mode 100644 index 0000000..f20ad35a --- /dev/null +++ b/third_party/crashpad/crashpad/minidump/minidump_byte_array_writer_test.cc
@@ -0,0 +1,80 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "minidump/minidump_byte_array_writer.h" + +#include <memory> + +#include "base/format_macros.h" +#include "base/strings/stringprintf.h" +#include "gtest/gtest.h" +#include "minidump/test/minidump_writable_test_util.h" +#include "util/file/string_file.h" + +namespace crashpad { +namespace test { +namespace { + +TEST(MinidumpByteArrayWriter, Write) { + const std::vector<uint8_t> kTests[] = { + {'h', 'e', 'l', 'l', 'o'}, + {0x42, 0x99, 0x00, 0xbe}, + {0x00}, + {}, + }; + + for (size_t i = 0; i < arraysize(kTests); ++i) { + SCOPED_TRACE(base::StringPrintf("index %" PRIuS, i)); + + StringFile string_file; + + crashpad::MinidumpByteArrayWriter writer; + writer.set_data(kTests[i]); + EXPECT_TRUE(writer.WriteEverything(&string_file)); + + ASSERT_EQ(string_file.string().size(), + sizeof(MinidumpByteArray) + kTests[i].size()); + + auto byte_array = std::make_unique<MinidumpByteArray>(); + EXPECT_EQ(string_file.Seek(0, SEEK_SET), 0); + string_file.Read(byte_array.get(), sizeof(*byte_array)); + + EXPECT_EQ(byte_array->length, kTests[i].size()); + + std::vector<uint8_t> data(byte_array->length); + string_file.Read(data.data(), byte_array->length); + + EXPECT_EQ(data, kTests[i]); + } +} + +TEST(MinidumpByteArrayWriter, SetData) { + const std::vector<uint8_t> kTests[] = { + {1, 2, 3, 4, 5}, + {0x0}, + {}, + }; + + for (size_t i = 0; i < arraysize(kTests); ++i) { + SCOPED_TRACE(base::StringPrintf("index %" PRIuS, i)); + + crashpad::MinidumpByteArrayWriter writer; + writer.set_data(kTests[i].data(), kTests[i].size()); + EXPECT_EQ(writer.data(), kTests[i]); + } +} + +} // namespace +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/minidump/minidump_context_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_context_writer.cc index c6c29d9..218d7775a 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_context_writer.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_context_writer.cc
@@ -23,6 +23,7 @@ #include "base/logging.h" #include "snapshot/cpu_context.h" #include "util/file/file_writer.h" +#include "util/stdlib/aligned_allocator.h" namespace crashpad { @@ -65,10 +66,8 @@ } case kCPUArchitectureX86_64: { - MSVC_PUSH_DISABLE_WARNING(4316); // Object on heap may not be aligned. MinidumpContextAMD64Writer* context_amd64 = new MinidumpContextAMD64Writer(); - MSVC_POP_WARNING(); // C4316 context.reset(context_amd64); context_amd64->InitializeFromSnapshot(context_snapshot->x86_64); break; @@ -152,6 +151,12 @@ return sizeof(context_); } +static_assert(alignof(MinidumpContextAMD64) >= 16, + "MinidumpContextAMD64 alignment"); +static_assert(alignof(MinidumpContextAMD64Writer) >= + alignof(MinidumpContextAMD64), + "MinidumpContextAMD64Writer alignment"); + MinidumpContextAMD64Writer::MinidumpContextAMD64Writer() : MinidumpContextWriter(), context_() { context_.context_flags = kMinidumpContextAMD64; @@ -160,6 +165,20 @@ MinidumpContextAMD64Writer::~MinidumpContextAMD64Writer() { } +// static +void* MinidumpContextAMD64Writer::operator new(size_t size) { + // MinidumpContextAMD64 requests an alignment of 16, which can be larger than + // what standard new provides. This may trigger MSVC warning C4316. As a + // workaround to this language deficiency, provide a custom allocation + // function to allocate a block meeting the alignment requirement. + return AlignedAllocate(alignof(MinidumpContextAMD64Writer), size); +} + +// static +void MinidumpContextAMD64Writer::operator delete(void* pointer) { + return AlignedFree(pointer); +} + void MinidumpContextAMD64Writer::InitializeFromSnapshot( const CPUContextX86_64* context_snapshot) { DCHECK_EQ(state(), kStateMutable);
diff --git a/third_party/crashpad/crashpad/minidump/minidump_context_writer.h b/third_party/crashpad/crashpad/minidump/minidump_context_writer.h index 29bc3ee..25d717e 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_context_writer.h +++ b/third_party/crashpad/crashpad/minidump/minidump_context_writer.h
@@ -110,6 +110,16 @@ MinidumpContextAMD64Writer(); ~MinidumpContextAMD64Writer() override; + // Ensure proper alignment of heap-allocated objects. This should not be + // necessary in C++17. + static void* operator new(size_t size); + static void operator delete(void* ptr); + + // Prevent unaligned heap-allocated arrays. Provisions could be made to allow + // these if necessary, but there is currently no use for them. + static void* operator new[](size_t size) = delete; + static void operator delete[](void* ptr) = delete; + //! \brief Initializes the MinidumpContextAMD64 based on \a context_snapshot. //! //! \param[in] context_snapshot The context snapshot to use as source data.
diff --git a/third_party/crashpad/crashpad/minidump/minidump_context_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_context_writer_test.cc index 0c2b5ea2..82b4db7 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_context_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_context_writer_test.cc
@@ -69,6 +69,15 @@ } TEST(MinidumpContextWriter, MinidumpContextAMD64Writer) { + { + // Make sure that a heap-allocated context writer has the proper alignment, + // because it may be nonstandard. + auto context_writer = std::make_unique<MinidumpContextAMD64Writer>(); + EXPECT_EQ(reinterpret_cast<uintptr_t>(context_writer.get()) & + (alignof(MinidumpContextAMD64Writer) - 1), + 0u); + } + StringFile string_file; {
diff --git a/third_party/crashpad/crashpad/minidump/minidump_extensions.h b/third_party/crashpad/crashpad/minidump/minidump_extensions.h index f361566..ad69aecb 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_extensions.h +++ b/third_party/crashpad/crashpad/minidump/minidump_extensions.h
@@ -118,6 +118,17 @@ uint8_t Buffer[0]; }; +//! \brief A variable-length array of bytes carried within a minidump file. +//! The data have no intrinsic type and should be interpreted according +//! to their referencing context. +struct ALIGNAS(4) PACKED MinidumpByteArray { + //! \brief The length of the #data field. + uint32_t length; + + //! \brief The bytes of data. + uint8_t data[0]; +}; + //! \brief CPU type values for MINIDUMP_SYSTEM_INFO::ProcessorArchitecture. //! //! \sa \ref PROCESSOR_ARCHITECTURE_x "PROCESSOR_ARCHITECTURE_*"
diff --git a/third_party/crashpad/crashpad/minidump/minidump_file_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_file_writer_test.cc index 448ee60b..e41ed75f 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_file_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_file_writer_test.cc
@@ -21,6 +21,7 @@ #include <utility> #include "base/compiler_specific.h" +#include "build/build_config.h" #include "gtest/gtest.h" #include "minidump/minidump_stream_writer.h" #include "minidump/minidump_user_extension_stream_data_source.h" @@ -395,9 +396,18 @@ // In a 32-bit environment, this will give a “timestamp out of range” warning, // but the test should complete without failure. constexpr uint32_t kSnapshotTime = 0xfd469ab8; +#if defined(COMPILER_GCC) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconstant-conversion" +#define DISABLED_WCONSTANT_CONVERSION +#endif // COMPILER_GCC || __clang__ MSVC_SUPPRESS_WARNING(4309); // Truncation of constant value. MSVC_SUPPRESS_WARNING(4838); // Narrowing conversion. constexpr timeval kSnapshotTimeval = {static_cast<time_t>(kSnapshotTime), 0}; +#if defined(DISABLED_WCONSTANT_CONVERSION) +#pragma GCC diagnostic pop +#undef DISABLED_WCONSTANT_CONVERSION +#endif // DISABLED_WCONSTANT_CONVERSION TestProcessSnapshot process_snapshot; process_snapshot.SetSnapshotTime(kSnapshotTimeval);
diff --git a/third_party/crashpad/crashpad/minidump/minidump_test.gyp b/third_party/crashpad/crashpad/minidump/minidump_test.gyp index 80f803db..beb4151 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_test.gyp +++ b/third_party/crashpad/crashpad/minidump/minidump_test.gyp
@@ -29,6 +29,8 @@ '..', ], 'sources': [ + 'test/minidump_byte_array_writer_test_util.cc', + 'test/minidump_byte_array_writer_test_util.h', 'test/minidump_context_test_util.cc', 'test/minidump_context_test_util.h', 'test/minidump_file_writer_test_util.cc', @@ -62,6 +64,7 @@ '..', ], 'sources': [ + 'minidump_byte_array_writer_test.cc', 'minidump_context_writer_test.cc', 'minidump_crashpad_info_writer_test.cc', 'minidump_exception_writer_test.cc',
diff --git a/third_party/crashpad/crashpad/minidump/minidump_thread_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_thread_writer_test.cc index 3e8e7de..60173da2 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_thread_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_thread_writer_test.cc
@@ -220,13 +220,7 @@ kMemoryBase, kMemorySize, kMemoryValue); thread_writer->SetStack(std::move(memory_writer)); - // Object allocated on heap may not be aligned. - MSVC_PUSH_DISABLE_WARNING(4316); - // This would use std::make_unique, but since the “new” would be in <memory> - // and not here, MSVC_PUSH_DISABLE_WARNING wouldn’t have the intended effect. - std::unique_ptr<MinidumpContextAMD64Writer> context_amd64_writer( - new MinidumpContextAMD64Writer()); - MSVC_POP_WARNING(); // C4316. + auto context_amd64_writer = std::make_unique<MinidumpContextAMD64Writer>(); InitializeMinidumpContextAMD64(context_amd64_writer->context(), kSeed); thread_writer->SetContext(std::move(context_amd64_writer));
diff --git a/third_party/crashpad/crashpad/minidump/test/minidump_byte_array_writer_test_util.cc b/third_party/crashpad/crashpad/minidump/test/minidump_byte_array_writer_test_util.cc new file mode 100644 index 0000000..01e9d0a6 --- /dev/null +++ b/third_party/crashpad/crashpad/minidump/test/minidump_byte_array_writer_test_util.cc
@@ -0,0 +1,36 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "minidump/test/minidump_byte_array_writer_test_util.h" + +#include "minidump/test/minidump_writable_test_util.h" + +namespace crashpad { +namespace test { + +std::vector<uint8_t> MinidumpByteArrayAtRVA(const std::string& file_contents, + RVA rva) { + auto* minidump_byte_array = + MinidumpWritableAtRVA<MinidumpByteArray>(file_contents, rva); + if (!minidump_byte_array) { + return {}; + } + auto* data = static_cast<const uint8_t*>(minidump_byte_array->data); + const uint8_t* data_end = data + minidump_byte_array->length; + return std::vector<uint8_t>(data, data_end); +} + + +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/minidump/test/minidump_byte_array_writer_test_util.h b/third_party/crashpad/crashpad/minidump/test/minidump_byte_array_writer_test_util.h new file mode 100644 index 0000000..d2c926b --- /dev/null +++ b/third_party/crashpad/crashpad/minidump/test/minidump_byte_array_writer_test_util.h
@@ -0,0 +1,43 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef MINIDUMP_TEST_MINIDUMP_BYTE_ARRAY_WRITER_TEST_UTIL_H_ +#define MINIDUMP_TEST_MINIDUMP_BYTE_ARRAY_WRITER_TEST_UTIL_H_ + +#include <windows.h> +#include <dbghelp.h> +#include <stdint.h> + +#include <string> +#include <vector> + +namespace crashpad { +namespace test { + +//! \brief Returns the bytes referenced by a MinidumpByteArray object located +//! in a minidump file at the specified RVA. +//! +//! \param[in] file_contents The contents of the minidump file. +//! \param[in] rva The offset in the minidump file of the MinidumpByteArray. +//! +//! \return The MinidumpByteArray::data referenced by the \a rva. Note that +//! this function does not check that the data are within the bounds of +//! the \a file_contents. +std::vector<uint8_t> MinidumpByteArrayAtRVA(const std::string& file_contents, + RVA rva); + +} // namespace test +} // namespace crashpad + +#endif // MINIDUMP_TEST_MINIDUMP_BYTE_ARRAY_WRITER_TEST_UTIL_H_
diff --git a/third_party/crashpad/crashpad/snapshot/annotation_snapshot.cc b/third_party/crashpad/crashpad/snapshot/annotation_snapshot.cc new file mode 100644 index 0000000..c3350ec --- /dev/null +++ b/third_party/crashpad/crashpad/snapshot/annotation_snapshot.cc
@@ -0,0 +1,32 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "snapshot/annotation_snapshot.h" + +namespace crashpad { + +AnnotationSnapshot::AnnotationSnapshot() : name(), type(0), value() {} + +AnnotationSnapshot::AnnotationSnapshot(const std::string& name, + uint16_t type, + const std::vector<uint8_t>& value) + : name(name), type(type), value(value) {} + +AnnotationSnapshot::~AnnotationSnapshot() = default; + +bool AnnotationSnapshot::operator==(const AnnotationSnapshot& other) const { + return name == other.name && type == other.type && value == other.value; +} + +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/annotation_snapshot.h b/third_party/crashpad/crashpad/snapshot/annotation_snapshot.h new file mode 100644 index 0000000..11de475 --- /dev/null +++ b/third_party/crashpad/crashpad/snapshot/annotation_snapshot.h
@@ -0,0 +1,54 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_SNAPSHOT_ANNOTATION_SNAPSHOT_H_ +#define CRASHPAD_SNAPSHOT_ANNOTATION_SNAPSHOT_H_ + +#include <stdint.h> + +#include <string> +#include <vector> + +namespace crashpad { + +// \!brief The snapshot representation of a client's Annotation. +struct AnnotationSnapshot { + AnnotationSnapshot(); + AnnotationSnapshot(const std::string& name, + uint16_t type, + const std::vector<uint8_t>& value); + ~AnnotationSnapshot(); + + bool operator==(const AnnotationSnapshot& other) const; + bool operator!=(const AnnotationSnapshot& other) const { + return !(*this == other); + } + + //! \brief A non-unique name by which this annotation can be identified. + std::string name; + + //! \brief The Annotation::Type of data stored in the annotation. This value + //! may be client-supplied and need not correspond to a Crashpad-defined + //! type. + uint16_t type; + + //! \brief The data for the annotation. Guranteed to be non-empty, since + //! empty annotations are skipped. The representation of the data should + //! be interpreted as \a #type. + std::vector<uint8_t> value; +}; + +} // namespace crashpad + +#endif // CRASHPAD_SNAPSHOT_ANNOTATION_SNAPSHOT_H_
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc b/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc index 697c14e..45f3f17 100644 --- a/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc +++ b/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc
@@ -141,13 +141,10 @@ TEST(CrashpadInfoClientOptions, TwoModules) { // Open the module, which has its own CrashpadInfo structure. -#if defined(OS_MACOSX) - const base::FilePath::StringType kDlExtension = FILE_PATH_LITERAL(".so"); -#elif defined(OS_WIN) - const base::FilePath::StringType kDlExtension = FILE_PATH_LITERAL(".dll"); -#endif - base::FilePath module_path = TestPaths::Executable().DirName().Append( - FILE_PATH_LITERAL("crashpad_snapshot_test_module") + kDlExtension); + base::FilePath module_path = + TestPaths::BuildArtifact(FILE_PATH_LITERAL("snapshot"), + FILE_PATH_LITERAL("module"), + TestPaths::FileType::kLoadableModule); #if defined(OS_MACOSX) ScopedModuleHandle module( dlopen(module_path.value().c_str(), RTLD_LAZY | RTLD_LOCAL));
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.cc index df8bebad..1a74d812 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.cc
@@ -25,6 +25,7 @@ #include "client/simple_string_dictionary.h" #include "snapshot/mac/mach_o_image_reader.h" #include "snapshot/mac/process_reader.h" +#include "snapshot/snapshot_constants.h" #include "util/mach/task_memory.h" #include "util/stdlib/strnlen.h" @@ -57,6 +58,15 @@ return simple_map_annotations; } +std::vector<AnnotationSnapshot> MachOImageAnnotationsReader::AnnotationsList() + const { + std::vector<AnnotationSnapshot> annotations; + + ReadCrashpadAnnotationsList(&annotations); + + return annotations; +} + void MachOImageAnnotationsReader::ReadCrashReporterClientAnnotations( std::vector<std::string>* vector_annotations) const { mach_vm_address_t crash_info_address; @@ -173,4 +183,64 @@ } } +// TODO(rsesek): When there is a platform-agnostic remote memory reader +// interface available, use it so that the implementation is not duplicated +// in the PEImageAnnotationsReader. +void MachOImageAnnotationsReader::ReadCrashpadAnnotationsList( + std::vector<AnnotationSnapshot>* annotations) const { + process_types::CrashpadInfo crashpad_info; + if (!image_reader_->GetCrashpadInfo(&crashpad_info)) { + return; + } + + if (!crashpad_info.annotations_list) { + return; + } + + process_types::AnnotationList annotation_list_object; + if (!annotation_list_object.Read(process_reader_, + crashpad_info.annotations_list)) { + LOG(WARNING) << "could not read annotations list object in " << name_; + return; + } + + process_types::Annotation current = annotation_list_object.head; + for (size_t index = 0; + current.link_node != annotation_list_object.tail_pointer && + index < kMaxNumberOfAnnotations; + ++index) { + if (!current.Read(process_reader_, current.link_node)) { + LOG(WARNING) << "could not read annotation at index " << index << " in " + << name_; + return; + } + + if (current.size == 0) { + continue; + } + + AnnotationSnapshot snapshot; + snapshot.type = current.type; + snapshot.value.resize(current.size); + + if (!process_reader_->Memory()->ReadCStringSizeLimited( + current.name, Annotation::kNameMaxLength, &snapshot.name)) { + LOG(WARNING) << "could not read annotation name at index " << index + << " in " << name_; + continue; + } + + size_t size = + std::min(static_cast<size_t>(current.size), Annotation::kValueMaxSize); + if (!process_reader_->Memory()->Read( + current.value, size, snapshot.value.data())) { + LOG(WARNING) << "could not read annotation value at index " << index + << " in " << name_; + continue; + } + + annotations->push_back(std::move(snapshot)); + } +} + } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.h b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.h index 2ff6e0e..06d2bea 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.h +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader.h
@@ -20,6 +20,7 @@ #include <vector> #include "base/macros.h" +#include "snapshot/annotation_snapshot.h" #include "snapshot/mac/process_types.h" namespace crashpad { @@ -67,6 +68,10 @@ //! pairs, where all keys and values are strings. std::map<std::string, std::string> SimpleMap() const; + //! \brief Returns the module’s annotations that are organized as a list of + // typed annotation objects. + std::vector<AnnotationSnapshot> AnnotationsList() const; + private: // Reades crashreporter_annotations_t::message and // crashreporter_annotations_t::message2 on behalf of Vector(). @@ -81,6 +86,10 @@ void ReadCrashpadSimpleAnnotations( std::map<std::string, std::string>* simple_map_annotations) const; + // Reads CrashpadInfo::annotations_list_ on behalf of AnnotationsList(). + void ReadCrashpadAnnotationsList( + std::vector<AnnotationSnapshot>* vector_annotations) const; + std::string name_; ProcessReader* process_reader_; // weak const MachOImageReader* image_reader_; // weak
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader_test.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader_test.cc index 68d6c4e..3e7864b 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader_test.cc
@@ -28,6 +28,8 @@ #include "base/files/file_path.h" #include "base/macros.h" +#include "client/annotation.h" +#include "client/annotation_list.h" #include "client/crashpad_info.h" #include "client/simple_string_dictionary.h" #include "gtest/gtest.h" @@ -49,13 +51,16 @@ namespace { // \return The path to crashpad_snapshot_test_module_crashy_initializer.so -std::string ModuleWithCrashyInitializer() { - return TestPaths::Executable().value() + "_module_crashy_initializer.so"; +base::FilePath ModuleWithCrashyInitializer() { + return TestPaths::BuildArtifact("snapshot", + "module_crashy_initializer", + TestPaths::FileType::kLoadableModule); } //! \return The path to the crashpad_snapshot_test_no_op executable. base::FilePath NoOpExecutable() { - return base::FilePath(TestPaths::Executable().value() + "_no_op"); + return TestPaths::BuildArtifact( + "snapshot", "no_op", TestPaths::FileType::kExecutable); } class TestMachOImageAnnotationsReader final @@ -181,7 +186,7 @@ case kCrashModuleInitialization: // This message is set by dyld-353.2.1/src/ImageLoaderMachO.cpp // ImageLoaderMachO::doInitialization(). - expected_annotation = ModuleWithCrashyInitializer(); + expected_annotation = ModuleWithCrashyInitializer().value(); break; case kCrashDyld: @@ -248,10 +253,12 @@ char c; CheckedReadFileExactly(ReadPipeHandle(), &c, sizeof(c)); - // Verify the “simple map” annotations set via the CrashpadInfo interface. + // Verify the “simple map” and object-based annotations set via the + // CrashpadInfo interface. const std::vector<ProcessReader::Module>& modules = process_reader.Modules(); std::map<std::string, std::string> all_annotations_simple_map; + std::vector<AnnotationSnapshot> all_annotations; for (const ProcessReader::Module& module : modules) { MachOImageAnnotationsReader module_annotations_reader( &process_reader, module.reader, module.name); @@ -259,6 +266,11 @@ module_annotations_reader.SimpleMap(); all_annotations_simple_map.insert(module_annotations_simple_map.begin(), module_annotations_simple_map.end()); + + std::vector<AnnotationSnapshot> annotations = + module_annotations_reader.AnnotationsList(); + all_annotations.insert( + all_annotations.end(), annotations.begin(), annotations.end()); } EXPECT_GE(all_annotations_simple_map.size(), 5u); @@ -268,6 +280,31 @@ EXPECT_EQ(all_annotations_simple_map["#TEST# longer"], "shorter"); EXPECT_EQ(all_annotations_simple_map["#TEST# empty_value"], ""); + EXPECT_EQ(all_annotations.size(), 3u); + bool saw_same_name_3 = false, saw_same_name_4 = false; + for (const auto& annotation : all_annotations) { + EXPECT_EQ(annotation.type, + static_cast<uint16_t>(Annotation::Type::kString)); + std::string value(reinterpret_cast<const char*>(annotation.value.data()), + annotation.value.size()); + + if (annotation.name == "#TEST# one") { + EXPECT_EQ(value, "moocow"); + } else if (annotation.name == "#TEST# same-name") { + if (value == "same-name 3") { + EXPECT_FALSE(saw_same_name_3); + saw_same_name_3 = true; + } else if (value == "same-name 4") { + EXPECT_FALSE(saw_same_name_4); + saw_same_name_4 = true; + } else { + ADD_FAILURE() << "unexpected annotation value " << value; + } + } else { + ADD_FAILURE() << "unexpected annotation " << annotation.name; + } + } + // Tell the child process that it’s permitted to crash. CheckedWriteFile(WritePipeHandle(), &c, sizeof(c)); @@ -329,6 +366,19 @@ crashpad_info->set_simple_annotations(simple_annotations); + AnnotationList::Register(); // This is “leaked” to crashpad_info. + + static StringAnnotation<32> test_annotation_one{"#TEST# one"}; + static StringAnnotation<32> test_annotation_two{"#TEST# two"}; + static StringAnnotation<32> test_annotation_three{"#TEST# same-name"}; + static StringAnnotation<32> test_annotation_four{"#TEST# same-name"}; + + test_annotation_one.Set("moocow"); + test_annotation_two.Set("this will be cleared"); + test_annotation_three.Set("same-name 3"); + test_annotation_four.Set("same-name 4"); + test_annotation_two.Clear(); + // Tell the parent that the environment has been set up. char c = '\0'; CheckedWriteFile(WritePipeHandle(), &c, sizeof(c)); @@ -355,7 +405,7 @@ case kCrashModuleInitialization: { // Load a module that crashes while executing a module initializer. - void* dl_handle = dlopen(ModuleWithCrashyInitializer().c_str(), + void* dl_handle = dlopen(ModuleWithCrashyInitializer().value().c_str(), RTLD_LAZY | RTLD_LOCAL); // This should have crashed in the dlopen(). If dlopen() failed, the
diff --git a/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.cc index 272c8c1..2d75037 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.cc
@@ -185,6 +185,12 @@ return annotations_reader.SimpleMap(); } +std::vector<AnnotationSnapshot> ModuleSnapshotMac::AnnotationObjects() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + NOTREACHED(); + return {}; +} + std::set<CheckedRange<uint64_t>> ModuleSnapshotMac::ExtraMemoryRanges() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return std::set<CheckedRange<uint64_t>>();
diff --git a/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.h b/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.h index 16ad7e1..44c07910 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.h +++ b/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.h
@@ -79,6 +79,7 @@ std::string DebugFileName() const override; std::vector<std::string> AnnotationsVector() const override; std::map<std::string, std::string> AnnotationsSimpleMap() const override; + std::vector<AnnotationSnapshot> AnnotationObjects() const override; std::set<CheckedRange<uint64_t>> ExtraMemoryRanges() const override; std::vector<const UserMinidumpStream*> CustomMinidumpStreams() const override;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc index 36b372fb..c9f39e715 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc
@@ -42,16 +42,6 @@ #include "util/misc/from_pointer_cast.h" #include "util/synchronization/semaphore.h" -#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10 -extern "C" { - -// Redeclare a typedef whose availability (OS X 10.10) is newer than the -// deployment target. -typedef struct _cl_device_id* cl_device_id; - -} // extern "C" -#endif - namespace crashpad { namespace test { namespace { @@ -574,10 +564,24 @@ cl_int rv = clGetPlatformIDs(1, &platform_id, nullptr); ASSERT_EQ(rv, CL_SUCCESS) << "clGetPlatformIDs"; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10 && \ + MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10 + // cl_device_id is really available in OpenCL.framework back to 10.5, but in + // the 10.10 SDK and later, OpenCL.framework includes <OpenGL/CGLDevice.h>, + // which has its own cl_device_id that was introduced in 10.10. That + // triggers erroneous availability warnings. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +#define DISABLED_WUNGUARDED_AVAILABILITY +#endif // SDK >= 10.10 && DT < 10.10 // Use CL_DEVICE_TYPE_CPU to ensure that the kernel would execute on the // CPU. This is the only device type that a cl_kernels image will be created // for. cl_device_id device_id; +#if defined(DISABLED_WUNGUARDED_AVAILABILITY) +#pragma clang diagnostic pop +#undef DISABLED_WUNGUARDED_AVAILABILITY +#endif // DISABLED_WUNGUARDED_AVAILABILITY rv = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_CPU, 1, &device_id, nullptr); ASSERT_EQ(rv, CL_SUCCESS) << "clGetDeviceIDs";
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types/all.proctype b/third_party/crashpad/crashpad/snapshot/mac/process_types/all.proctype index 7ef54d5..d84b41d1 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types/all.proctype +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types/all.proctype
@@ -19,6 +19,7 @@ // snapshot/mac/process_types.cc to produce process type struct definitions and // accessors. +#include "snapshot/mac/process_types/annotation.proctype" #include "snapshot/mac/process_types/crashpad_info.proctype" #include "snapshot/mac/process_types/crashreporterclient.proctype" #include "snapshot/mac/process_types/dyld_images.proctype"
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types/annotation.proctype b/third_party/crashpad/crashpad/snapshot/mac/process_types/annotation.proctype new file mode 100644 index 0000000..5d34fda --- /dev/null +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types/annotation.proctype
@@ -0,0 +1,31 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +PROCESS_TYPE_STRUCT_BEGIN(Annotation) + PROCESS_TYPE_STRUCT_MEMBER(Pointer, link_node) + PROCESS_TYPE_STRUCT_MEMBER(Pointer, name) + PROCESS_TYPE_STRUCT_MEMBER(Pointer, value) + PROCESS_TYPE_STRUCT_MEMBER(uint32_t, size) + PROCESS_TYPE_STRUCT_MEMBER(uint16_t, type) +PROCESS_TYPE_STRUCT_END(Annotation) + +#if !defined(PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY) + +PROCESS_TYPE_STRUCT_BEGIN(AnnotationList) + PROCESS_TYPE_STRUCT_MEMBER(Pointer, tail_pointer) + PROCESS_TYPE_STRUCT_MEMBER(crashpad::process_types::Annotation, head) + PROCESS_TYPE_STRUCT_MEMBER(crashpad::process_types::Annotation, tail) +PROCESS_TYPE_STRUCT_END(AnnotationList) + +#endif // !defined(PROCESS_TYPE_STRUCT_IMPLEMENT_ARRAY)
diff --git a/third_party/crashpad/crashpad/snapshot/minidump/module_snapshot_minidump.cc b/third_party/crashpad/crashpad/snapshot/minidump/module_snapshot_minidump.cc index f5132270..195fc89 100644 --- a/third_party/crashpad/crashpad/snapshot/minidump/module_snapshot_minidump.cc +++ b/third_party/crashpad/crashpad/snapshot/minidump/module_snapshot_minidump.cc
@@ -135,6 +135,13 @@ return annotations_simple_map_; } +std::vector<AnnotationSnapshot> ModuleSnapshotMinidump::AnnotationObjects() + const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + NOTREACHED(); + return {}; +} + std::set<CheckedRange<uint64_t>> ModuleSnapshotMinidump::ExtraMemoryRanges() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_);
diff --git a/third_party/crashpad/crashpad/snapshot/minidump/module_snapshot_minidump.h b/third_party/crashpad/crashpad/snapshot/minidump/module_snapshot_minidump.h index 3d63f2a..ad65dbc9 100644 --- a/third_party/crashpad/crashpad/snapshot/minidump/module_snapshot_minidump.h +++ b/third_party/crashpad/crashpad/snapshot/minidump/module_snapshot_minidump.h
@@ -76,6 +76,7 @@ std::string DebugFileName() const override; std::vector<std::string> AnnotationsVector() const override; std::map<std::string, std::string> AnnotationsSimpleMap() const override; + std::vector<AnnotationSnapshot> AnnotationObjects() const override; std::set<CheckedRange<uint64_t>> ExtraMemoryRanges() const override; std::vector<const UserMinidumpStream*> CustomMinidumpStreams() const override;
diff --git a/third_party/crashpad/crashpad/snapshot/module_snapshot.h b/third_party/crashpad/crashpad/snapshot/module_snapshot.h index cd3dbd3..eea7466 100644 --- a/third_party/crashpad/crashpad/snapshot/module_snapshot.h +++ b/third_party/crashpad/crashpad/snapshot/module_snapshot.h
@@ -24,6 +24,7 @@ #include <string> #include <vector> +#include "snapshot/annotation_snapshot.h" #include "snapshot/memory_snapshot.h" #include "util/misc/uuid.h" #include "util/numeric/checked_range.h" @@ -172,7 +173,7 @@ //! (`dyld`) can provide an annotation at its `_error_string` symbol. //! //! The annotations returned by this method do not duplicate those returned by - //! AnnotationsSimpleMap(). + //! AnnotationsSimpleMap() or AnnotationObjects(). virtual std::vector<std::string> AnnotationsVector() const = 0; //! \brief Returns key-value string annotations recorded in the module. @@ -190,11 +191,27 @@ //! method. For clients such as Chrome, this includes the process type. //! //! The annotations returned by this method do not duplicate those returned by - //! AnnotationsVector(). Additional annotations related to the process, - //! system, or snapshot producer may be obtained by calling + //! AnnotationsVector() or AnnotationObjects(). Additional annotations related + //! to the process, system, or snapshot producer may be obtained by calling //! ProcessSnapshot::AnnotationsSimpleMap(). virtual std::map<std::string, std::string> AnnotationsSimpleMap() const = 0; + //! \brief Returns the typed annotation objects recorded in the module. + //! + //! This method retrieves annotations recorded in a module. These annotations + //! are intended for diagnostic use, including crash analysis. Annotation + //! objects are strongly-typed name-value pairs. The names are not unique. + //! + //! For macOS snapshots, these annotations are found by interpreting the + //! `__DATA,crashpad_info` section as `CrashpadInfo`. Clients can use the + //! Crashpad client interface to store annotations in this structure. Most + //! annotations under the client’s direct control will be retrievable by this + //! method. For clients such as Chrome, this includes the process type. + //! + //! The annotations returned by this method do not duplicate those returned by + //! AnnotationsVector() or AnnotationsSimpleMap(). + virtual std::vector<AnnotationSnapshot> AnnotationObjects() const = 0; + //! \brief Returns a set of extra memory ranges specified in the module as //! being desirable to include in the crash dump. virtual std::set<CheckedRange<uint64_t>> ExtraMemoryRanges() const = 0;
diff --git a/third_party/crashpad/crashpad/snapshot/snapshot.gyp b/third_party/crashpad/crashpad/snapshot/snapshot.gyp index 4b5e8c94..73a5da0 100644 --- a/third_party/crashpad/crashpad/snapshot/snapshot.gyp +++ b/third_party/crashpad/crashpad/snapshot/snapshot.gyp
@@ -30,6 +30,8 @@ '..', ], 'sources': [ + 'annotation_snapshot.cc', + 'annotation_snapshot.h', 'capture_memory.cc', 'capture_memory.h', 'cpu_architecture.h', @@ -84,6 +86,7 @@ 'mac/process_types.cc', 'mac/process_types.h', 'mac/process_types/all.proctype', + 'mac/process_types/annotation.proctype', 'mac/process_types/crashpad_info.proctype', 'mac/process_types/crashreporterclient.proctype', 'mac/process_types/custom.cc', @@ -112,6 +115,7 @@ 'posix/timezone.cc', 'posix/timezone.h', 'process_snapshot.h', + 'snapshot_constants.h', 'system_snapshot.h', 'thread_snapshot.h', 'unloaded_module_snapshot.cc',
diff --git a/third_party/crashpad/crashpad/snapshot/snapshot_constants.h b/third_party/crashpad/crashpad/snapshot/snapshot_constants.h new file mode 100644 index 0000000..2bbddda --- /dev/null +++ b/third_party/crashpad/crashpad/snapshot/snapshot_constants.h
@@ -0,0 +1,28 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SNAPSHOT_SNAPSHOT_CONSTANTS_H_ +#define SNAPSHOT_SNAPSHOT_CONSTANTS_H_ + +namespace crashpad { + +//! \brief The maximum number of crashpad::Annotations that will be read from +//! a client process. +//! +//! \note This maximum was chosen arbitrarily and may change in the future. +constexpr size_t kMaxNumberOfAnnotations = 200; + +} // namespace crashpad + +#endif // SNAPSHOT_SNAPSHOT_CONSTANTS_H_
diff --git a/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp b/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp index 4b6db39..d720a10e 100644 --- a/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp +++ b/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp
@@ -67,9 +67,9 @@ '..', ], 'sources': [ + 'api/module_annotations_win_test.cc', 'cpu_context_test.cc', 'crashpad_info_client_options_test.cc', - 'api/module_annotations_win_test.cc', 'elf/elf_image_reader_test.cc', 'linux/debug_rendezvous_test.cc', 'linux/exception_snapshot_linux_test.cc', @@ -107,8 +107,10 @@ }], ['OS=="win"', { 'dependencies': [ + 'crashpad_snapshot_test_annotations', 'crashpad_snapshot_test_crashing_child', 'crashpad_snapshot_test_dump_without_crashing', + 'crashpad_snapshot_test_extra_memory_ranges', 'crashpad_snapshot_test_image_reader', 'crashpad_snapshot_test_image_reader_module', ], @@ -247,7 +249,7 @@ }, }, { - 'target_name': 'crashpad_snapshot_test_simple_annotations', + 'target_name': 'crashpad_snapshot_test_annotations', 'type': 'executable', 'dependencies': [ '../client/client.gyp:crashpad_client', @@ -255,7 +257,7 @@ '../third_party/mini_chromium/mini_chromium.gyp:base', ], 'sources': [ - 'win/crashpad_snapshot_test_simple_annotations.cc', + 'win/crashpad_snapshot_test_annotations.cc', ], }, ],
diff --git a/third_party/crashpad/crashpad/snapshot/test/test_module_snapshot.cc b/third_party/crashpad/crashpad/snapshot/test/test_module_snapshot.cc index 47962ce..9141edad 100644 --- a/third_party/crashpad/crashpad/snapshot/test/test_module_snapshot.cc +++ b/third_party/crashpad/crashpad/snapshot/test/test_module_snapshot.cc
@@ -94,6 +94,10 @@ return annotations_simple_map_; } +std::vector<AnnotationSnapshot> TestModuleSnapshot::AnnotationObjects() const { + return annotation_objects_; +} + std::set<CheckedRange<uint64_t>> TestModuleSnapshot::ExtraMemoryRanges() const { return extra_memory_ranges_; }
diff --git a/third_party/crashpad/crashpad/snapshot/test/test_module_snapshot.h b/third_party/crashpad/crashpad/snapshot/test/test_module_snapshot.h index 92b3f094..d1262fa6 100644 --- a/third_party/crashpad/crashpad/snapshot/test/test_module_snapshot.h +++ b/third_party/crashpad/crashpad/snapshot/test/test_module_snapshot.h
@@ -75,6 +75,10 @@ const std::map<std::string, std::string>& annotations_simple_map) { annotations_simple_map_ = annotations_simple_map; } + void SetAnnotationObjects( + const std::vector<AnnotationSnapshot>& annotations) { + annotation_objects_ = annotations; + } void SetExtraMemoryRanges( const std::set<CheckedRange<uint64_t>>& extra_memory_ranges) { extra_memory_ranges_ = extra_memory_ranges; @@ -99,6 +103,7 @@ std::string DebugFileName() const override; std::vector<std::string> AnnotationsVector() const override; std::map<std::string, std::string> AnnotationsSimpleMap() const override; + std::vector<AnnotationSnapshot> AnnotationObjects() const override; std::set<CheckedRange<uint64_t>> ExtraMemoryRanges() const override; std::vector<const UserMinidumpStream*> CustomMinidumpStreams() const override; @@ -115,6 +120,7 @@ std::string debug_file_name_; std::vector<std::string> annotations_vector_; std::map<std::string, std::string> annotations_simple_map_; + std::vector<AnnotationSnapshot> annotation_objects_; std::set<CheckedRange<uint64_t>> extra_memory_ranges_; DISALLOW_COPY_AND_ASSIGN(TestModuleSnapshot);
diff --git a/third_party/crashpad/crashpad/snapshot/win/cpu_context_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/cpu_context_win_test.cc index 41adde3..aa2afe9 100644 --- a/third_party/crashpad/crashpad/snapshot/win/cpu_context_win_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/cpu_context_win_test.cc
@@ -80,9 +80,9 @@ EXPECT_EQ(cpu_context_x86.fxsave.fsw, 0x0004); EXPECT_EQ(cpu_context_x86.fxsave.ftw, 0x00f0); EXPECT_EQ(cpu_context_x86.fxsave.fop, 0x0bad); - EXPECT_EQ(cpu_context_x86.fxsave.fpu_ip, 0x01234567); + EXPECT_EQ(cpu_context_x86.fxsave.fpu_ip, 0x01234567u); EXPECT_EQ(cpu_context_x86.fxsave.fpu_cs, 0x0003); - EXPECT_EQ(cpu_context_x86.fxsave.fpu_dp, 0x89abcdef); + EXPECT_EQ(cpu_context_x86.fxsave.fpu_dp, 0x89abcdefu); EXPECT_EQ(cpu_context_x86.fxsave.fpu_ds, 0x0007); for (size_t st_mm = 0; st_mm < 7; ++st_mm) { EXPECT_EQ(
diff --git a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_simple_annotations.cc b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_annotations.cc similarity index 75% rename from third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_simple_annotations.cc rename to third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_annotations.cc index 11e7b4e..6005f4d 100644 --- a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_simple_annotations.cc +++ b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_annotations.cc
@@ -15,6 +15,8 @@ #include <windows.h> #include "base/logging.h" +#include "client/annotation.h" +#include "client/annotation_list.h" #include "client/crashpad_info.h" #include "util/file/file_io.h" @@ -34,6 +36,20 @@ crashpad_info->set_simple_annotations(simple_annotations); + // Set the annotation objects. + crashpad::AnnotationList::Register(); + + static crashpad::StringAnnotation<32> annotation_one("#TEST# one"); + static crashpad::StringAnnotation<32> annotation_two("#TEST# two"); + static crashpad::StringAnnotation<32> annotation_three("#TEST# same-name"); + static crashpad::StringAnnotation<32> annotation_four("#TEST# same-name"); + + annotation_one.Set("moocow"); + annotation_two.Set("this will be cleared"); + annotation_three.Set("same-name 3"); + annotation_four.Set("same-name 4"); + annotation_two.Clear(); + // Tell the parent that the environment has been set up. HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); PCHECK(out != INVALID_HANDLE_VALUE) << "GetStdHandle";
diff --git a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_image_reader.cc b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_image_reader.cc index 6f4203d..4ebd98e9 100644 --- a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_image_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_image_reader.cc
@@ -28,7 +28,7 @@ // Allocate a bunch of pointers to things on the stack. int* pointers[1000]; - for (int i = 0; i < arraysize(pointers); ++i) { + for (size_t i = 0; i < arraysize(pointers); ++i) { pointers[i] = new int[2048]; } @@ -52,7 +52,7 @@ // verify the cap on pointed-to memory. crashpad::Semaphore semaphore(0); crashpad::ScopedKernelHANDLE threads[100]; - for (int i = 0; i < arraysize(threads); ++i) { + for (size_t i = 0; i < arraysize(threads); ++i) { threads[i].reset(CreateThread(nullptr, 0, &LotsOfReferencesThreadProc, @@ -65,7 +65,7 @@ } } - for (int i = 0; i < arraysize(threads); ++i) { + for (size_t i = 0; i < arraysize(threads); ++i) { semaphore.Wait(); }
diff --git a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc index a782ae6..843ad263 100644 --- a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc
@@ -121,7 +121,7 @@ DISALLOW_COPY_AND_ASSIGN(CrashingDelegate); }; -void TestCrashingChild(const base::FilePath& directory) { +void TestCrashingChild(TestPaths::Architecture architecture) { // Set up the registration server on a background thread. ScopedKernelHANDLE server_ready(CreateEvent(nullptr, false, false, nullptr)); ASSERT_TRUE(server_ready.is_valid()) << ErrorMessage("CreateEvent"); @@ -141,13 +141,11 @@ << ErrorMessage("WaitForSingleObject"); // Spawn a child process, passing it the pipe name to connect to. - std::wstring child_test_executable = directory - .Append(TestPaths::Executable() - .BaseName() - .RemoveFinalExtension() - .value() + - L"_crashing_child.exe") - .value(); + base::FilePath child_test_executable = + TestPaths::BuildArtifact(L"snapshot", + L"crashing_child", + TestPaths::FileType::kExecutable, + architecture); ChildLauncher child(child_test_executable, pipe_name); ASSERT_NO_FATAL_FAILURE(child.Start()); @@ -166,17 +164,16 @@ } TEST(ExceptionSnapshotWinTest, ChildCrash) { - TestCrashingChild(TestPaths::Executable().DirName()); + TestCrashingChild(TestPaths::Architecture::kDefault); } #if defined(ARCH_CPU_64_BITS) TEST(ExceptionSnapshotWinTest, ChildCrashWOW64) { - base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory(); - if (output_32_bit_directory.empty()) { + if (!TestPaths::Has32BitBuildArtifacts()) { DISABLED_TEST(); } - TestCrashingChild(output_32_bit_directory); + TestCrashingChild(TestPaths::Architecture::k32Bit); } #endif // ARCH_CPU_64_BITS @@ -203,7 +200,7 @@ exception_information_address, debug_critical_section_address); EXPECT_TRUE(snapshot.Exception()); - EXPECT_EQ(snapshot.Exception()->Exception(), 0x517a7ed); + EXPECT_EQ(snapshot.Exception()->Exception(), 0x517a7edu); // Verify the dump was captured at the expected location with some slop // space. @@ -229,7 +226,7 @@ DISALLOW_COPY_AND_ASSIGN(SimulateDelegate); }; -void TestDumpWithoutCrashingChild(const base::FilePath& directory) { +void TestDumpWithoutCrashingChild(TestPaths::Architecture architecture) { // Set up the registration server on a background thread. ScopedKernelHANDLE server_ready(CreateEvent(nullptr, false, false, nullptr)); ASSERT_TRUE(server_ready.is_valid()) << ErrorMessage("CreateEvent"); @@ -249,14 +246,11 @@ << ErrorMessage("WaitForSingleObject"); // Spawn a child process, passing it the pipe name to connect to. - std::wstring child_test_executable = - directory - .Append(TestPaths::Executable() - .BaseName() - .RemoveFinalExtension() - .value() + - L"_dump_without_crashing.exe") - .value(); + base::FilePath child_test_executable = + TestPaths::BuildArtifact(L"snapshot", + L"dump_without_crashing", + TestPaths::FileType::kExecutable, + architecture); ChildLauncher child(child_test_executable, pipe_name); ASSERT_NO_FATAL_FAILURE(child.Start()); @@ -271,21 +265,20 @@ EXPECT_EQ(WaitForSingleObject(completed.get(), INFINITE), WAIT_OBJECT_0) << ErrorMessage("WaitForSingleObject"); - EXPECT_EQ(child.WaitForExit(), 0); + EXPECT_EQ(child.WaitForExit(), 0u); } TEST(SimulateCrash, ChildDumpWithoutCrashing) { - TestDumpWithoutCrashingChild(TestPaths::Executable().DirName()); + TestDumpWithoutCrashingChild(TestPaths::Architecture::kDefault); } #if defined(ARCH_CPU_64_BITS) TEST(SimulateCrash, ChildDumpWithoutCrashingWOW64) { - base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory(); - if (output_32_bit_directory.empty()) { + if (!TestPaths::Has32BitBuildArtifacts()) { DISABLED_TEST(); } - TestDumpWithoutCrashingChild(output_32_bit_directory); + TestDumpWithoutCrashingChild(TestPaths::Architecture::k32Bit); } #endif // ARCH_CPU_64_BITS
diff --git a/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc b/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc index d0820a0..dcef805 100644 --- a/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/extra_memory_ranges_test.cc
@@ -43,15 +43,14 @@ kCrashDebugBreak, }; -void TestExtraMemoryRanges(TestType type, const base::FilePath& directory) { +void TestExtraMemoryRanges(TestType type, + TestPaths::Architecture architecture) { // Spawn a child process, passing it the pipe name to connect to. - std::wstring child_test_executable = directory - .Append(TestPaths::Executable() - .BaseName() - .RemoveFinalExtension() - .value() + - L"_extra_memory_ranges.exe") - .value(); + base::FilePath child_test_executable = + TestPaths::BuildArtifact(L"snapshot", + L"extra_memory_ranges", + TestPaths::FileType::kExecutable, + architecture); ChildLauncher child(child_test_executable, L""); ASSERT_NO_FATAL_FAILURE(child.Start()); @@ -101,30 +100,28 @@ } TEST(ExtraMemoryRanges, DontCrash) { - TestExtraMemoryRanges(kDontCrash, TestPaths::Executable().DirName()); + TestExtraMemoryRanges(kDontCrash, TestPaths::Architecture::kDefault); } TEST(ExtraMemoryRanges, CrashDebugBreak) { - TestExtraMemoryRanges(kCrashDebugBreak, TestPaths::Executable().DirName()); + TestExtraMemoryRanges(kCrashDebugBreak, TestPaths::Architecture::kDefault); } #if defined(ARCH_CPU_64_BITS) TEST(ExtraMemoryRanges, DontCrashWOW64) { - base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory(); - if (output_32_bit_directory.empty()) { + if (!TestPaths::Has32BitBuildArtifacts()) { DISABLED_TEST(); } - TestExtraMemoryRanges(kDontCrash, output_32_bit_directory); + TestExtraMemoryRanges(kDontCrash, TestPaths::Architecture::k32Bit); } TEST(ExtraMemoryRanges, CrashDebugBreakWOW64) { - base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory(); - if (output_32_bit_directory.empty()) { + if (!TestPaths::Has32BitBuildArtifacts()) { DISABLED_TEST(); } - TestExtraMemoryRanges(kCrashDebugBreak, output_32_bit_directory); + TestExtraMemoryRanges(kCrashDebugBreak, TestPaths::Architecture::k32Bit); } #endif // ARCH_CPU_64_BITS
diff --git a/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.cc b/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.cc index ec0bab5..b130eccb 100644 --- a/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.cc +++ b/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.cc
@@ -190,6 +190,12 @@ return annotations_reader.SimpleMap(); } +std::vector<AnnotationSnapshot> ModuleSnapshotWin::AnnotationObjects() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + NOTREACHED(); + return {}; +} + std::set<CheckedRange<uint64_t>> ModuleSnapshotWin::ExtraMemoryRanges() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::set<CheckedRange<uint64_t>> ranges;
diff --git a/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.h b/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.h index 4cc7b84..2a7083d 100644 --- a/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.h +++ b/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.h
@@ -85,6 +85,7 @@ std::string DebugFileName() const override; std::vector<std::string> AnnotationsVector() const override; std::map<std::string, std::string> AnnotationsSimpleMap() const override; + std::vector<AnnotationSnapshot> AnnotationObjects() const override; std::set<CheckedRange<uint64_t>> ExtraMemoryRanges() const override; std::vector<const UserMinidumpStream*> CustomMinidumpStreams() const override;
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader.cc b/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader.cc index 87de1e3..4ef8a1eae 100644 --- a/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader.cc
@@ -18,13 +18,35 @@ #include <sys/types.h> #include "base/strings/utf_string_conversions.h" +#include "client/annotation.h" #include "client/simple_string_dictionary.h" +#include "snapshot/snapshot_constants.h" #include "snapshot/win/pe_image_reader.h" #include "snapshot/win/process_reader_win.h" #include "util/win/process_structs.h" namespace crashpad { +namespace process_types { + +template <class Traits> +struct Annotation { + typename Traits::Pointer link_node; + typename Traits::Pointer name; + typename Traits::Pointer value; + uint32_t size; + uint16_t type; +}; + +template <class Traits> +struct AnnotationList { + typename Traits::Pointer tail_pointer; + Annotation<Traits> head; + Annotation<Traits> tail; +}; + +} // namespace process_types + PEImageAnnotationsReader::PEImageAnnotationsReader( ProcessReaderWin* process_reader, const PEImageReader* pe_image_reader, @@ -46,6 +68,19 @@ return simple_map_annotations; } +std::vector<AnnotationSnapshot> PEImageAnnotationsReader::AnnotationsList() + const { + std::vector<AnnotationSnapshot> annotations; + if (process_reader_->Is64Bit()) { + ReadCrashpadAnnotationsList<process_types::internal::Traits64>( + &annotations); + } else { + ReadCrashpadAnnotationsList<process_types::internal::Traits32>( + &annotations); + } + return annotations; +} + template <class Traits> void PEImageAnnotationsReader::ReadCrashpadSimpleAnnotations( std::map<std::string, std::string>* simple_map_annotations) const { @@ -80,4 +115,71 @@ } } +// TODO(rsesek): When there is a platform-agnostic remote memory reader +// interface available, use it so that the implementation is not duplicated +// in the MachOImageAnnotationsReader. +template <class Traits> +void PEImageAnnotationsReader::ReadCrashpadAnnotationsList( + std::vector<AnnotationSnapshot>* vector_annotations) const { + process_types::CrashpadInfo<Traits> crashpad_info; + if (!pe_image_reader_->GetCrashpadInfo(&crashpad_info)) { + return; + } + + if (!crashpad_info.annotations_list) { + return; + } + + process_types::AnnotationList<Traits> annotation_list_object; + if (!process_reader_->ReadMemory(crashpad_info.annotations_list, + sizeof(annotation_list_object), + &annotation_list_object)) { + LOG(WARNING) << "could not read annotations list object in " + << base::UTF16ToUTF8(name_); + return; + } + + process_types::Annotation<Traits> current = annotation_list_object.head; + for (size_t index = 0; + current.link_node != annotation_list_object.tail_pointer && + index < kMaxNumberOfAnnotations; + ++index) { + if (!process_reader_->ReadMemory( + current.link_node, sizeof(current), ¤t)) { + LOG(WARNING) << "could not read annotation at index " << index << " in " + << base::UTF16ToUTF8(name_); + return; + } + + if (current.size == 0) { + continue; + } + + AnnotationSnapshot snapshot; + snapshot.type = current.type; + + char name[Annotation::kNameMaxLength]; + if (!process_reader_->ReadMemory(current.name, arraysize(name), name)) { + LOG(WARNING) << "could not read annotation name at index " << index + << " in " << base::UTF16ToUTF8(name_); + continue; + } + + size_t name_length = strnlen(name, Annotation::kNameMaxLength); + snapshot.name = std::string(name, name_length); + + size_t value_length = + std::min(static_cast<size_t>(current.size), Annotation::kValueMaxSize); + snapshot.value.resize(value_length); + if (!process_reader_->ReadMemory( + current.value, value_length, snapshot.value.data())) { + LOG(WARNING) << "could not read annotation value at index " << index + << " in " << base::UTF16ToUTF8(name_); + continue; + } + + vector_annotations->push_back(std::move(snapshot)); + } +} + } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader.h b/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader.h index 85f3bed..6379b27 100644 --- a/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader.h +++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader.h
@@ -20,6 +20,7 @@ #include <vector> #include "base/macros.h" +#include "snapshot/annotation_snapshot.h" namespace crashpad { @@ -54,12 +55,21 @@ //! pairs, where all keys and values are strings. std::map<std::string, std::string> SimpleMap() const; + //! \brief Returns the module's annotations that are organized as a list of + //! typed annotation objects. + std::vector<AnnotationSnapshot> AnnotationsList() const; + private: // Reads CrashpadInfo::simple_annotations_ on behalf of SimpleMap(). template <class Traits> void ReadCrashpadSimpleAnnotations( std::map<std::string, std::string>* simple_map_annotations) const; + // Reads CrashpadInfo::annotations_list_ on behalf of AnnotationsList(). + template <class Traits> + void ReadCrashpadAnnotationsList( + std::vector<AnnotationSnapshot>* vector_annotations) const; + std::wstring name_; ProcessReaderWin* process_reader_; // weak const PEImageReader* pe_image_reader_; // weak
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader_test.cc b/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader_test.cc index f69f5ab..f576394 100644 --- a/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_annotations_reader_test.cc
@@ -27,6 +27,7 @@ #include "client/crashpad_info.h" #include "client/simple_string_dictionary.h" #include "gtest/gtest.h" +#include "snapshot/annotation_snapshot.h" #include "snapshot/win/pe_image_reader.h" #include "snapshot/win/process_reader_win.h" #include "test/gtest_disabled.h" @@ -47,15 +48,14 @@ kCrashDebugBreak, }; -void TestAnnotationsOnCrash(TestType type, const base::FilePath& directory) { +void TestAnnotationsOnCrash(TestType type, + TestPaths::Architecture architecture) { // Spawn a child process, passing it the pipe name to connect to. - std::wstring child_test_executable = directory - .Append(TestPaths::Executable() - .BaseName() - .RemoveFinalExtension() - .value() + - L"_simple_annotations.exe") - .value(); + base::FilePath child_test_executable = + TestPaths::BuildArtifact(L"snapshot", + L"annotations", + TestPaths::FileType::kExecutable, + architecture); ChildLauncher child(child_test_executable, L""); ASSERT_NO_FATAL_FAILURE(child.Start()); @@ -68,9 +68,11 @@ ASSERT_TRUE(process_reader.Initialize(child.process_handle(), ProcessSuspensionState::kRunning)); - // Verify the "simple map" annotations set via the CrashpadInfo interface. + // Read all the kinds of annotations referenced from the CrashpadInfo + // structure. const std::vector<ProcessInfo::Module>& modules = process_reader.Modules(); std::map<std::string, std::string> all_annotations_simple_map; + std::vector<AnnotationSnapshot> all_annotation_objects; for (const ProcessInfo::Module& module : modules) { PEImageReader pe_image_reader; pe_image_reader.Initialize(&process_reader, @@ -79,12 +81,19 @@ base::UTF16ToUTF8(module.name)); PEImageAnnotationsReader module_annotations_reader( &process_reader, &pe_image_reader, module.name); + std::map<std::string, std::string> module_annotations_simple_map = module_annotations_reader.SimpleMap(); all_annotations_simple_map.insert(module_annotations_simple_map.begin(), module_annotations_simple_map.end()); + + auto module_annotations_list = module_annotations_reader.AnnotationsList(); + all_annotation_objects.insert(all_annotation_objects.end(), + module_annotations_list.begin(), + module_annotations_list.end()); } + // Verify the "simple map" annotations. EXPECT_GE(all_annotations_simple_map.size(), 5u); EXPECT_EQ(all_annotations_simple_map["#TEST# pad"], "crash"); EXPECT_EQ(all_annotations_simple_map["#TEST# key"], "value"); @@ -92,6 +101,32 @@ EXPECT_EQ(all_annotations_simple_map["#TEST# longer"], "shorter"); EXPECT_EQ(all_annotations_simple_map["#TEST# empty_value"], ""); + // Verify the typed annotation objects. + EXPECT_EQ(all_annotation_objects.size(), 3); + bool saw_same_name_3 = false, saw_same_name_4 = false; + for (const auto& annotation : all_annotation_objects) { + EXPECT_EQ(annotation.type, + static_cast<uint16_t>(Annotation::Type::kString)); + std::string value(reinterpret_cast<const char*>(annotation.value.data()), + annotation.value.size()); + + if (annotation.name == "#TEST# one") { + EXPECT_EQ(value, "moocow"); + } else if (annotation.name == "#TEST# same-name") { + if (value == "same-name 3") { + EXPECT_FALSE(saw_same_name_3); + saw_same_name_3 = true; + } else if (value == "same-name 4") { + EXPECT_FALSE(saw_same_name_4); + saw_same_name_4 = true; + } else { + ADD_FAILURE() << "unexpected annotation value " << value; + } + } else { + ADD_FAILURE() << "unexpected annotation " << annotation.name; + } + } + // Tell the child process to continue. DWORD expected_exit_code; switch (type) { @@ -112,30 +147,28 @@ } TEST(PEImageAnnotationsReader, DontCrash) { - TestAnnotationsOnCrash(kDontCrash, TestPaths::Executable().DirName()); + TestAnnotationsOnCrash(kDontCrash, TestPaths::Architecture::kDefault); } TEST(PEImageAnnotationsReader, CrashDebugBreak) { - TestAnnotationsOnCrash(kCrashDebugBreak, TestPaths::Executable().DirName()); + TestAnnotationsOnCrash(kCrashDebugBreak, TestPaths::Architecture::kDefault); } #if defined(ARCH_CPU_64_BITS) TEST(PEImageAnnotationsReader, DontCrashWOW64) { - base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory(); - if (output_32_bit_directory.empty()) { + if (!TestPaths::Has32BitBuildArtifacts()) { DISABLED_TEST(); } - TestAnnotationsOnCrash(kDontCrash, output_32_bit_directory); + TestAnnotationsOnCrash(kDontCrash, TestPaths::Architecture::k32Bit); } TEST(PEImageAnnotationsReader, CrashDebugBreakWOW64) { - base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory(); - if (output_32_bit_directory.empty()) { + if (!TestPaths::Has32BitBuildArtifacts()) { DISABLED_TEST(); } - TestAnnotationsOnCrash(kCrashDebugBreak, output_32_bit_directory); + TestAnnotationsOnCrash(kCrashDebugBreak, TestPaths::Architecture::k32Bit); } #endif // ARCH_CPU_64_BITS
diff --git a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader_test.cc b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader_test.cc index bf53279..3192a44 100644 --- a/third_party/crashpad/crashpad/snapshot/win/pe_image_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/pe_image_reader_test.cc
@@ -22,6 +22,7 @@ #include "gtest/gtest.h" #include "snapshot/win/process_reader_win.h" #include "test/errors.h" +#include "test/test_paths.h" #include "util/misc/from_pointer_cast.h" #include "util/win/get_module_information.h" #include "util/win/module_version.h" @@ -52,7 +53,11 @@ DWORD age; std::string pdbname; EXPECT_TRUE(pe_image_reader.DebugDirectoryInformation(&uuid, &age, &pdbname)); - EXPECT_NE(pdbname.find("crashpad_snapshot_test"), std::string::npos); + std::string self_name = base::UTF16ToUTF8( + TestPaths::ExpectedExecutableBasename(L"crashpad_snapshot_test") + .RemoveFinalExtension() + .value()); + EXPECT_NE(pdbname.find(self_name), std::string::npos); const std::string suffix(".pdb"); EXPECT_EQ( pdbname.compare(pdbname.size() - suffix.size(), suffix.size(), suffix), @@ -73,13 +78,14 @@ ASSERT_TRUE(observed_rv || !known_dll); if (observed_rv) { - EXPECT_EQ(observed.dwSignature, VS_FFI_SIGNATURE); - EXPECT_EQ(observed.dwStrucVersion, VS_FFI_STRUCVERSION); - EXPECT_EQ(observed.dwFileFlags & ~observed.dwFileFlagsMask, 0); - EXPECT_EQ(observed.dwFileOS, VOS_NT_WINDOWS32); + EXPECT_EQ(observed.dwSignature, static_cast<DWORD>(VS_FFI_SIGNATURE)); + EXPECT_EQ(observed.dwStrucVersion, static_cast<DWORD>(VS_FFI_STRUCVERSION)); + EXPECT_EQ(observed.dwFileFlags & ~observed.dwFileFlagsMask, 0u); if (known_dll) { - EXPECT_EQ(observed.dwFileType, VFT_DLL); + EXPECT_EQ(observed.dwFileOS, static_cast<DWORD>(VOS_NT_WINDOWS32)); + EXPECT_EQ(observed.dwFileType, static_cast<DWORD>(VFT_DLL)); } else { + EXPECT_NE(observed.dwFileOS & VOS_NT_WINDOWS32, 0u); EXPECT_TRUE(observed.dwFileType == VFT_APP || observed.dwFileType == VFT_DLL); }
diff --git a/third_party/crashpad/crashpad/snapshot/win/process_reader_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/process_reader_win_test.cc index 9e62e11..d0d4d96 100644 --- a/third_party/crashpad/crashpad/snapshot/win/process_reader_win_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/process_reader_win_test.cc
@@ -107,12 +107,12 @@ EXPECT_EQ(threads[0].id, GetCurrentThreadId()); #if defined(ARCH_CPU_64_BITS) - EXPECT_NE(threads[0].context.native.Rip, 0); + EXPECT_NE(threads[0].context.native.Rip, 0u); #else EXPECT_NE(threads[0].context.native.Eip, 0u); #endif - EXPECT_EQ(threads[0].suspend_count, 0); + EXPECT_EQ(threads[0].suspend_count, 0u); } class ProcessReaderChildThreadSuspendCount final : public WinMultiprocess { @@ -188,7 +188,7 @@ // the pipe. CheckedReadFileAtEOF(ReadPipeHandle()); - for (int i = 0; i < arraysize(threads); ++i) + for (size_t i = 0; i < arraysize(threads); ++i) done.Signal(); for (auto& thread : threads) thread.Join();
diff --git a/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc index 839ba48..b2448fc 100644 --- a/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/process_snapshot_win_test.cc
@@ -31,20 +31,18 @@ namespace test { namespace { -void TestImageReaderChild(const base::FilePath& directory) { +void TestImageReaderChild(const TestPaths::Architecture architecture) { UUID done_uuid; done_uuid.InitializeWithNew(); ScopedKernelHANDLE done( CreateEvent(nullptr, true, false, done_uuid.ToString16().c_str())); ASSERT_TRUE(done.is_valid()) << ErrorMessage("CreateEvent"); - std::wstring child_test_executable = directory - .Append(TestPaths::Executable() - .BaseName() - .RemoveFinalExtension() - .value() + - L"_image_reader.exe") - .value(); + base::FilePath child_test_executable = + TestPaths::BuildArtifact(L"snapshot", + L"image_reader", + TestPaths::FileType::kExecutable, + architecture); ChildLauncher child(child_test_executable, done_uuid.ToString16()); ASSERT_NO_FATAL_FAILURE(child.Start()); @@ -109,21 +107,20 @@ // Tell the child it can terminate. EXPECT_TRUE(SetEvent(done.get())) << ErrorMessage("SetEvent"); - EXPECT_EQ(child.WaitForExit(), 0); + EXPECT_EQ(child.WaitForExit(), 0u); } TEST(ProcessSnapshotTest, CrashpadInfoChild) { - TestImageReaderChild(TestPaths::Executable().DirName()); + TestImageReaderChild(TestPaths::Architecture::kDefault); } #if defined(ARCH_CPU_64_BITS) TEST(ProcessSnapshotTest, CrashpadInfoChildWOW64) { - base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory(); - if (output_32_bit_directory.empty()) { + if (!TestPaths::Has32BitBuildArtifacts()) { DISABLED_TEST(); } - TestImageReaderChild(output_32_bit_directory); + TestImageReaderChild(TestPaths::Architecture::k32Bit); } #endif
diff --git a/third_party/crashpad/crashpad/util/file/filesystem_test_util.cc b/third_party/crashpad/crashpad/test/filesystem.cc similarity index 98% rename from third_party/crashpad/crashpad/util/file/filesystem_test_util.cc rename to third_party/crashpad/crashpad/test/filesystem.cc index 5d991ee7..a9a73f6a 100644 --- a/third_party/crashpad/crashpad/util/file/filesystem_test_util.cc +++ b/third_party/crashpad/crashpad/test/filesystem.cc
@@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "util/file/filesystem_test_util.h" +#include "test/filesystem.h" #include <errno.h> #include <sys/stat.h>
diff --git a/third_party/crashpad/crashpad/util/file/filesystem_test_util.h b/third_party/crashpad/crashpad/test/filesystem.h similarity index 92% rename from third_party/crashpad/crashpad/util/file/filesystem_test_util.h rename to third_party/crashpad/crashpad/test/filesystem.h index b74653f..7e65845 100644 --- a/third_party/crashpad/crashpad/util/file/filesystem_test_util.h +++ b/third_party/crashpad/crashpad/test/filesystem.h
@@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef CRASHPAD_UTIL_FILE_FILESYSTEM_TEST_UTIL_H_ -#define CRASHPAD_UTIL_FILE_FILESYSTEM_TEST_UTIL_H_ +#ifndef CRASHPAD_TEST_FILESYSTEM_H_ +#define CRASHPAD_TEST_FILESYSTEM_H_ #include "base/files/file_path.h" @@ -56,4 +56,4 @@ } // namespace test } // namespace crashpad -#endif // CRASHPAD_UTIL_FILE_FILESYSTEM_TEST_UTIL_H_ +#endif // CRASHPAD_TEST_FILESYSTEM_H_
diff --git a/third_party/crashpad/crashpad/test/gtest_main.cc b/third_party/crashpad/crashpad/test/gtest_main.cc index 6e082828..d8c2a904 100644 --- a/third_party/crashpad/crashpad/test/gtest_main.cc +++ b/third_party/crashpad/crashpad/test/gtest_main.cc
@@ -33,15 +33,6 @@ int main(int argc, char* argv[]) { crashpad::test::InitializeMainArguments(argc, argv); - -#if defined(CRASHPAD_TEST_LAUNCHER_GMOCK) - testing::InitGoogleMock(&argc, argv); -#elif defined(CRASHPAD_TEST_LAUNCHER_GTEST) - testing::InitGoogleTest(&argc, argv); -#else // CRASHPAD_TEST_LAUNCHER_GTEST -#error #define CRASHPAD_TEST_LAUNCHER_GTEST or CRASHPAD_TEST_LAUNCHER_GMOCK -#endif // CRASHPAD_TEST_LAUNCHER_GTEST - testing::AddGlobalTestEnvironment( crashpad::test::DisabledTestGtestEnvironment::Get()); @@ -69,5 +60,13 @@ #endif // CRASHPAD_IN_CHROMIUM +#if defined(CRASHPAD_TEST_LAUNCHER_GMOCK) + testing::InitGoogleMock(&argc, argv); +#elif defined(CRASHPAD_TEST_LAUNCHER_GTEST) + testing::InitGoogleTest(&argc, argv); +#else // CRASHPAD_TEST_LAUNCHER_GMOCK +#error #define CRASHPAD_TEST_LAUNCHER_GTEST or CRASHPAD_TEST_LAUNCHER_GMOCK +#endif // CRASHPAD_TEST_LAUNCHER_GMOCK + return RUN_ALL_TESTS(); }
diff --git a/third_party/crashpad/crashpad/test/multiprocess_exec.h b/third_party/crashpad/crashpad/test/multiprocess_exec.h index 9b2ffc1..258a3f8 100644 --- a/third_party/crashpad/crashpad/test/multiprocess_exec.h +++ b/third_party/crashpad/crashpad/test/multiprocess_exec.h
@@ -18,6 +18,7 @@ #include <string> #include <vector> +#include "base/files/file_path.h" #include "base/macros.h" #include "build/build_config.h" #include "test/multiprocess.h" @@ -48,7 +49,7 @@ //! process in its `argv[]` vector. This vector must begin at `argv[1]`, //! as \a command is implicitly used as `argv[0]`. This argument may be //! `nullptr` if no command-line arguments are to be passed. - void SetChildCommand(const std::string& command, + void SetChildCommand(const base::FilePath& command, const std::vector<std::string>* arguments); protected: @@ -61,7 +62,7 @@ // Multiprocess: void MultiprocessChild() override; - std::string command_; + base::FilePath command_; std::vector<std::string> arguments_; #if defined(OS_POSIX) std::vector<const char*> argv_;
diff --git a/third_party/crashpad/crashpad/test/multiprocess_exec_posix.cc b/third_party/crashpad/crashpad/test/multiprocess_exec_posix.cc index 3d7212d..528e8c7 100644 --- a/third_party/crashpad/crashpad/test/multiprocess_exec_posix.cc +++ b/third_party/crashpad/crashpad/test/multiprocess_exec_posix.cc
@@ -40,7 +40,8 @@ } void MultiprocessExec::SetChildCommand( - const std::string& command, const std::vector<std::string>* arguments) { + const base::FilePath& command, + const std::vector<std::string>* arguments) { command_ = command; if (arguments) { arguments_ = *arguments; @@ -62,7 +63,7 @@ // process, building it is a hazardous operation in that process. ASSERT_TRUE(argv_.empty()); - argv_.push_back(command_.c_str()); + argv_.push_back(command_.value().c_str()); for (const std::string& argument : arguments_) { argv_.push_back(argument.c_str()); }
diff --git a/third_party/crashpad/crashpad/test/multiprocess_exec_test.cc b/third_party/crashpad/crashpad/test/multiprocess_exec_test.cc index f35519a..b8a5bc194 100644 --- a/third_party/crashpad/crashpad/test/multiprocess_exec_test.cc +++ b/third_party/crashpad/crashpad/test/multiprocess_exec_test.cc
@@ -48,17 +48,10 @@ TEST(MultiprocessExec, MultiprocessExec) { TestMultiprocessExec multiprocess_exec; - base::FilePath test_executable = TestPaths::Executable(); -#if defined(OS_POSIX) - std::string child_test_executable = test_executable.value(); -#elif defined(OS_WIN) - std::string child_test_executable = - base::UTF16ToUTF8(test_executable.RemoveFinalExtension().value()); -#endif // OS_POSIX - child_test_executable += "_multiprocess_exec_test_child"; -#if defined(OS_WIN) - child_test_executable += ".exe"; -#endif + base::FilePath child_test_executable = TestPaths::BuildArtifact( + FILE_PATH_LITERAL("test"), + FILE_PATH_LITERAL("multiprocess_exec_test_child"), + TestPaths::FileType::kExecutable); multiprocess_exec.SetChildCommand(child_test_executable, nullptr); multiprocess_exec.Run(); }
diff --git a/third_party/crashpad/crashpad/test/multiprocess_exec_win.cc b/third_party/crashpad/crashpad/test/multiprocess_exec_win.cc index 5eb5d80..f3a10c4 100644 --- a/third_party/crashpad/crashpad/test/multiprocess_exec_win.cc +++ b/third_party/crashpad/crashpad/test/multiprocess_exec_win.cc
@@ -102,7 +102,7 @@ } void MultiprocessExec::SetChildCommand( - const std::string& command, + const base::FilePath& command, const std::vector<std::string>* arguments) { command_ = command; if (arguments) { @@ -119,7 +119,7 @@ ASSERT_FALSE(command_.empty()); command_line_.clear(); - AppendCommandLineArgument(base::UTF8ToUTF16(command_), &command_line_); + AppendCommandLineArgument(command_.value(), &command_line_); for (size_t i = 0; i < arguments_.size(); ++i) { AppendCommandLineArgument(base::UTF8ToUTF16(arguments_[i]), &command_line_); } @@ -154,7 +154,7 @@ startup_info.hStdOutput = info()->pipe_c2p_write.get(); startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); startup_info.dwFlags = STARTF_USESTDHANDLES; - PCHECK(CreateProcess(base::UTF8ToUTF16(command_).c_str(), + PCHECK(CreateProcess(command_.value().c_str(), &command_line_[0], // This cannot be constant, per MSDN. nullptr, nullptr,
diff --git a/third_party/crashpad/crashpad/test/test.gyp b/third_party/crashpad/crashpad/test/test.gyp index 931d948..4b38933 100644 --- a/third_party/crashpad/crashpad/test/test.gyp +++ b/third_party/crashpad/crashpad/test/test.gyp
@@ -35,6 +35,8 @@ 'errors.h', 'file.cc', 'file.h', + 'filesystem.cc', + 'filesystem.h', 'gtest_death_check.h', 'gtest_disabled.cc', 'gtest_disabled.h',
diff --git a/third_party/crashpad/crashpad/test/test_paths.cc b/third_party/crashpad/crashpad/test/test_paths.cc index a601208..ce180a37 100644 --- a/third_party/crashpad/crashpad/test/test_paths.cc +++ b/third_party/crashpad/crashpad/test/test_paths.cc
@@ -90,6 +90,23 @@ return base::FilePath(base::FilePath::kCurrentDirectory); } +#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS) + +// Returns the pathname of a directory containing 32-bit test build output. +// +// It would be better for this to be named 32BitOutputDirectory(), but that’s +// not a legal name. +base::FilePath Output32BitDirectory() { + const wchar_t* environment_value = _wgetenv(L"CRASHPAD_TEST_32_BIT_OUTPUT"); + if (!environment_value) { + return base::FilePath(); + } + + return base::FilePath(environment_value); +} + +#endif // defined(OS_WIN) && defined(ARCH_CPU_64_BITS) + } // namespace // static @@ -100,22 +117,84 @@ } // static +base::FilePath TestPaths::ExpectedExecutableBasename( + const base::FilePath::StringType& name) { +#if defined(CRASHPAD_IN_CHROMIUM) + base::FilePath::StringType executable_name( + FILE_PATH_LITERAL("crashpad_tests")); +#else // CRASHPAD_IN_CHROMIUM + base::FilePath::StringType executable_name(name); +#endif // CRASHPAD_IN_CHROMIUM + +#if defined(OS_WIN) + executable_name += FILE_PATH_LITERAL(".exe"); +#endif // OS_WIN + + return base::FilePath(executable_name); +} + +// static base::FilePath TestPaths::TestDataRoot() { static base::FilePath* test_data_root = new base::FilePath(TestDataRootInternal()); return *test_data_root; } +// static +base::FilePath TestPaths::BuildArtifact( + const base::FilePath::StringType& module, + const base::FilePath::StringType& artifact, + FileType file_type, + Architecture architecture) { + base::FilePath directory; + switch (architecture) { + case Architecture::kDefault: + directory = Executable().DirName(); + break; + +#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS) + case Architecture::k32Bit: + directory = Output32BitDirectory(); + CHECK(!directory.empty()); + break; +#endif // OS_WIN && ARCH_CPU_64_BITS + } + + base::FilePath::StringType test_name = + FILE_PATH_LITERAL("crashpad_") + module + FILE_PATH_LITERAL("_test"); +#if !defined(CRASHPAD_IN_CHROMIUM) + CHECK(Executable().BaseName().RemoveFinalExtension().value() == test_name); +#endif // !CRASHPAD_IN_CHROMIUM + + base::FilePath::StringType extension; + switch (file_type) { + case FileType::kNone: + break; + + case FileType::kExecutable: +#if defined(OS_WIN) + extension = FILE_PATH_LITERAL(".exe"); +#endif // OS_WIN + break; + + case FileType::kLoadableModule: +#if defined(OS_WIN) + extension = FILE_PATH_LITERAL(".dll"); +#else // OS_WIN + extension = FILE_PATH_LITERAL(".so"); +#endif // OS_WIN + break; + } + + return directory.Append(test_name + FILE_PATH_LITERAL("_") + artifact + + extension); +} + #if defined(OS_WIN) && defined(ARCH_CPU_64_BITS) // static -base::FilePath TestPaths::Output32BitDirectory() { - const wchar_t* environment_value = _wgetenv(L"CRASHPAD_TEST_32_BIT_OUTPUT"); - if (!environment_value) { - return base::FilePath(); - } - - return base::FilePath(environment_value); +bool TestPaths::Has32BitBuildArtifacts() { + return !Output32BitDirectory().empty(); } #endif // defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
diff --git a/third_party/crashpad/crashpad/test/test_paths.h b/third_party/crashpad/crashpad/test/test_paths.h index f5629ed..5540f77 100644 --- a/third_party/crashpad/crashpad/test/test_paths.h +++ b/third_party/crashpad/crashpad/test/test_paths.h
@@ -25,11 +25,61 @@ //! \brief Functions to obtain paths from within tests. class TestPaths { public: + //! \brief The type of file requested of BuildArtifact(). + //! + //! This is used to establish the file extension used by the returned path. + enum class FileType { + //! \brief No file extension is requested. + kNone = 0, + + //! \brief `.exe` will be used on Windows, and no file extension will be + //! used on other platforms. + kExecutable, + + //! \brief `.dll` will be used on Windows, and `.so` will be used on other + //! platforms. + kLoadableModule, + }; + + //! \brief The architecture of the file requested of BuildArtifact(). + enum class Architecture { + //! \brief The default architecture is requested. This is usually the same + //! architecture as the running process. + kDefault = 0, + +#if (defined(OS_WIN) && defined(ARCH_CPU_64_BITS)) || DOXYGEN + //! \brief The 32-bit variant is requested. + //! + //! On Windows, when running 64-bit code, the 32-bit variant can be + //! requested. Before doing so, Has32BitBuildArtifacts() must be called and + //! must return `true`. Otherwise, execution will be aborted. + k32Bit, +#endif // OS_WIN && ARCH_CPU_64_BITS + }; + //! \brief Returns the pathname of the currently-running test executable. //! //! On failure, aborts execution. static base::FilePath Executable(); + //! \brief Returns the expected basename of the currently-running test + //! executable. + //! + //! In Crashpad’s standalone build, this returns \a name, with the system’s + //! extension for executables (`.exe`) appended if appropriate. + //! + //! When building in Chromium, \a name is ignored, and the name of the + //! monolithic test executable (`crashpad_tests`) is returned, with the + //! system’s extension for executables appended if appropriate. + //! + //! Only use this function to determine test expectations. + //! + //! Do not use this function to obtain the name of the currently running test + //! executable, use Executable() instead. Do not use this function to locate + //! other build artifacts, use BuildArtifact() instead. + static base::FilePath ExpectedExecutableBasename( + const base::FilePath::StringType& name); + //! \brief Returns the pathname of the test data root. //! //! If the `CRASHPAD_TEST_DATA_ROOT` environment variable is set, its value @@ -43,21 +93,50 @@ //! files. static base::FilePath TestDataRoot(); + //! \brief Returns the pathname of a build artifact. + //! + //! \param[in] module The name of the Crashpad module associated with the + //! artifact, such as `"util"` or `"snapshot"`. \a module must correspond + //! to the module of the calling code, or execution will be aborted. + //! \param[in] artifact The name of the specific artifact. + //! \param[in] file_type The artifact’s type, used to establish the returned + //! path’s extension. + //! \param[in] architecture The artifact’s architecture. + //! + //! \return The computed pathname to the build artifact. + //! + //! For example, the following snippet will return a path to + //! `crashpad_snapshot_test_module.so` or `crashpad_snapshot_test_module.dll` + //! (depending on platform) in the same directory as the currently running + //! executable: + //! + //! \code + //! base::FilePath path = TestPaths::BuildArtifact( + //! FILE_PATH_LITERAL("snapshot"), + //! FILE_PATH_LITERAL("module"), + //! TestPaths::FileType::kLoadableModule); + //! \endcode + static base::FilePath BuildArtifact( + const base::FilePath::StringType& module, + const base::FilePath::StringType& artifact, + FileType file_type, + Architecture architecture = Architecture::kDefault); + #if (defined(OS_WIN) && defined(ARCH_CPU_64_BITS)) || DOXYGEN - //! \brief Returns the pathname of a directory containing 32-bit test build - //! output. + //! \return `true` if 32-bit build artifacts are available. //! //! Tests that require the use of 32-bit build output should call this - //! function to locate that output. This function is only provided to allow - //! 64-bit test code to locate 32-bit output. 32-bit test code can find 32-bit - //! output in its own directory, the parent of Executable(). + //! function to determine whether that output is available. This function is + //! only provided to aid 64-bit test code in locating 32-bit output. Only if + //! this function indicates that 32-bit output is available, 64-bit test code + //! may call BuildArtifact() with Architecture::k32Bit to obtain a path to the + //! 32-bit output. //! - //! If the `CRASHPAD_TEST_32_BIT_OUTPUT` environment variable is set, its - //! value will be returned. Otherwise, this function will return an empty - //! path, and tests that require the use of 32-bit build output should disable - //! themselves. The DISABLED_TEST() macro may be useful for this purpose. - static base::FilePath Output32BitDirectory(); -#endif + //! 32-bit test code may assume the existence of 32-bit build output, which + //! can be found its own directory, and located by calling BuildArtifact() + //! with Architecture::kDefault. + static bool Has32BitBuildArtifacts(); +#endif // OS_WIN && ARCH_CPU_64_BITS DISALLOW_IMPLICIT_CONSTRUCTORS(TestPaths); };
diff --git a/third_party/crashpad/crashpad/test/win/child_launcher.cc b/third_party/crashpad/crashpad/test/win/child_launcher.cc index c5f897c3..abd2e3d9 100644 --- a/third_party/crashpad/crashpad/test/win/child_launcher.cc +++ b/third_party/crashpad/crashpad/test/win/child_launcher.cc
@@ -21,15 +21,14 @@ namespace crashpad { namespace test { -ChildLauncher::ChildLauncher(const std::wstring& executable, +ChildLauncher::ChildLauncher(const base::FilePath& executable, const std::wstring& command_line) : executable_(executable), command_line_(command_line), process_handle_(), main_thread_handle_(), stdout_read_handle_(), - stdin_write_handle_() { -} + stdin_write_handle_() {} ChildLauncher::~ChildLauncher() { if (process_handle_.is_valid()) @@ -76,10 +75,10 @@ startup_info.dwFlags = STARTF_USESTDHANDLES; PROCESS_INFORMATION process_information; std::wstring command_line; - AppendCommandLineArgument(executable_, &command_line); + AppendCommandLineArgument(executable_.value(), &command_line); command_line += L" "; command_line += command_line_; - ASSERT_TRUE(CreateProcess(executable_.c_str(), + ASSERT_TRUE(CreateProcess(executable_.value().c_str(), &command_line[0], nullptr, nullptr,
diff --git a/third_party/crashpad/crashpad/test/win/child_launcher.h b/third_party/crashpad/crashpad/test/win/child_launcher.h index 6674efe..854e124 100644 --- a/third_party/crashpad/crashpad/test/win/child_launcher.h +++ b/third_party/crashpad/crashpad/test/win/child_launcher.h
@@ -19,6 +19,7 @@ #include <string> +#include "base/files/file_path.h" #include "util/win/scoped_handle.h" namespace crashpad { @@ -32,7 +33,7 @@ public: //! \brief Creates the object. \a executable will be escaped and prepended to //! \a command_line to build the command line of the child. - ChildLauncher(const std::wstring& executable, + ChildLauncher(const base::FilePath& executable, const std::wstring& command_line); ~ChildLauncher(); @@ -62,7 +63,7 @@ HANDLE stdin_write_handle() const { return stdin_write_handle_.get(); } private: - std::wstring executable_; + base::FilePath executable_; std::wstring command_line_; ScopedKernelHANDLE process_handle_; ScopedKernelHANDLE main_thread_handle_;
diff --git a/third_party/crashpad/crashpad/util/file/directory_reader_test.cc b/third_party/crashpad/crashpad/util/file/directory_reader_test.cc index 640b850..f03669e2 100644 --- a/third_party/crashpad/crashpad/util/file/directory_reader_test.cc +++ b/third_party/crashpad/crashpad/util/file/directory_reader_test.cc
@@ -21,11 +21,11 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "gtest/gtest.h" +#include "test/filesystem.h" #include "test/gtest_disabled.h" #include "test/scoped_temp_dir.h" #include "util/file/file_io.h" #include "util/file/filesystem.h" -#include "util/file/filesystem_test_util.h" namespace crashpad { namespace test {
diff --git a/third_party/crashpad/crashpad/util/file/filesystem_test.cc b/third_party/crashpad/crashpad/util/file/filesystem_test.cc index 8657e5b..7e28892 100644 --- a/third_party/crashpad/crashpad/util/file/filesystem_test.cc +++ b/third_party/crashpad/crashpad/util/file/filesystem_test.cc
@@ -17,9 +17,9 @@ #include "base/logging.h" #include "build/build_config.h" #include "gtest/gtest.h" +#include "test/filesystem.h" #include "test/gtest_disabled.h" #include "test/scoped_temp_dir.h" -#include "util/file/filesystem_test_util.h" namespace crashpad { namespace test {
diff --git a/third_party/crashpad/crashpad/util/misc/paths_test.cc b/third_party/crashpad/crashpad/util/misc/paths_test.cc index 1f373029..f0503ddc 100644 --- a/third_party/crashpad/crashpad/util/misc/paths_test.cc +++ b/third_party/crashpad/crashpad/util/misc/paths_test.cc
@@ -15,8 +15,8 @@ #include "util/misc/paths.h" #include "base/files/file_path.h" -#include "build/build_config.h" #include "gtest/gtest.h" +#include "test/test_paths.h" namespace crashpad { namespace test { @@ -26,12 +26,10 @@ base::FilePath executable_path; ASSERT_TRUE(Paths::Executable(&executable_path)); const base::FilePath executable_name(executable_path.BaseName()); -#if defined(OS_WIN) - EXPECT_EQ(executable_name.value(), - FILE_PATH_LITERAL("crashpad_util_test.exe")); -#else - EXPECT_EQ(executable_name.value(), "crashpad_util_test"); -#endif // OS_WIN + const base::FilePath expected_name(TestPaths::ExpectedExecutableBasename( + FILE_PATH_LITERAL("crashpad_util_test"))); + + EXPECT_EQ(executable_name.value(), expected_name.value()); } } // namespace
diff --git a/third_party/crashpad/crashpad/util/net/http_transport_test.cc b/third_party/crashpad/crashpad/util/net/http_transport_test.cc index 3b7e7eb..fc02ba1 100644 --- a/third_party/crashpad/crashpad/util/net/http_transport_test.cc +++ b/third_party/crashpad/crashpad/util/net/http_transport_test.cc
@@ -59,7 +59,7 @@ base::FilePath server_path = TestPaths::TestDataRoot().Append( FILE_PATH_LITERAL("util/net/http_transport_test_server.py")); #if defined(OS_POSIX) - SetChildCommand(server_path.value(), nullptr); + SetChildCommand(server_path, nullptr); #elif defined(OS_WIN) // Explicitly invoke a shell and python so that python can be found in the // path, and run the test script. @@ -67,7 +67,7 @@ args.push_back("/c"); args.push_back("python"); args.push_back(base::UTF16ToUTF8(server_path.value())); - SetChildCommand(getenv("COMSPEC"), &args); + SetChildCommand(base::FilePath(_wgetenv(L"COMSPEC")), &args); #endif // OS_POSIX }
diff --git a/third_party/crashpad/crashpad/util/net/http_transport_win.cc b/third_party/crashpad/crashpad/util/net/http_transport_win.cc index 9698df3..dc3eeeb 100644 --- a/third_party/crashpad/crashpad/util/net/http_transport_win.cc +++ b/third_party/crashpad/crashpad/util/net/http_transport_win.cc
@@ -101,6 +101,12 @@ GetLastError(), error_code); } + + // Most system messages end in a space. Remove the space if it’s there, + // because the StringPrintf() below includes one. + if (len >= 1 && msgbuf[len - 1] == ' ') { + msgbuf[len - 1] = '\0'; + } return base::StringPrintf("%s: %s (0x%lx)", extra, msgbuf, error_code); }
diff --git a/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.cc b/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.cc index 363022c..9aedb29 100644 --- a/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.cc +++ b/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.cc
@@ -42,7 +42,6 @@ } // namespace namespace crashpad { -namespace internal { void* AlignedAllocate(size_t alignment, size_t size) { #if defined(OS_POSIX) @@ -74,5 +73,4 @@ #endif // OS_POSIX } -} // namespace internal } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.h b/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.h index c3beb74..97be27a 100644 --- a/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.h +++ b/third_party/crashpad/crashpad/util/stdlib/aligned_allocator.h
@@ -24,7 +24,6 @@ #include <vector> namespace crashpad { -namespace internal { //! \brief Allocates memory with the specified alignment constraint. //! @@ -37,8 +36,6 @@ //! This function wraps `free()` or `_aligned_free()`. void AlignedFree(void* pointer); -} // namespace internal - //! \brief A standard allocator that aligns its allocations as requested, //! suitable for use as an allocator in standard containers. //! @@ -74,10 +71,10 @@ pointer allocate(size_type n, std::allocator<void>::const_pointer hint = 0) { return reinterpret_cast<pointer>( - internal::AlignedAllocate(Alignment, sizeof(value_type) * n)); + AlignedAllocate(Alignment, sizeof(value_type) * n)); } - void deallocate(pointer p, size_type n) { internal::AlignedFree(p); } + void deallocate(pointer p, size_type n) { AlignedFree(p); } size_type max_size() const noexcept { return std::numeric_limits<size_type>::max() / sizeof(value_type);
diff --git a/third_party/crashpad/crashpad/util/util_test.gyp b/third_party/crashpad/crashpad/util/util_test.gyp index ede3259..152c981 100644 --- a/third_party/crashpad/crashpad/util/util_test.gyp +++ b/third_party/crashpad/crashpad/util/util_test.gyp
@@ -40,8 +40,6 @@ 'file/file_io_test.cc', 'file/file_reader_test.cc', 'file/filesystem_test.cc', - 'file/filesystem_test_util.cc', - 'file/filesystem_test_util.h', 'file/string_file_test.cc', 'linux/auxiliary_vector_test.cc', 'linux/memory_map_test.cc',
diff --git a/third_party/crashpad/crashpad/util/win/process_info_test.cc b/third_party/crashpad/crashpad/util/win/process_info_test.cc index 051479d..709536b 100644 --- a/third_party/crashpad/crashpad/util/win/process_info_test.cc +++ b/third_party/crashpad/crashpad/util/win/process_info_test.cc
@@ -104,10 +104,12 @@ std::vector<ProcessInfo::Module> modules; EXPECT_TRUE(process_info.Modules(&modules)); ASSERT_GE(modules.size(), 2u); - static constexpr wchar_t kSelfName[] = L"\\crashpad_util_test.exe"; - ASSERT_GE(modules[0].name.size(), wcslen(kSelfName)); - EXPECT_EQ(modules[0].name.substr(modules[0].name.size() - wcslen(kSelfName)), - kSelfName); + std::wstring self_name = + std::wstring(1, '\\') + + TestPaths::ExpectedExecutableBasename(L"crashpad_util_test").value(); + ASSERT_GE(modules[0].name.size(), self_name.size()); + EXPECT_EQ(modules[0].name.substr(modules[0].name.size() - self_name.size()), + self_name); ASSERT_GE(modules[1].name.size(), wcslen(kNtdllName)); EXPECT_EQ(modules[1].name.substr(modules[1].name.size() - wcslen(kNtdllName)), kNtdllName); @@ -132,7 +134,7 @@ FromPointerCast<WinVMAddress>(_ReturnAddress())); } -void TestOtherProcess(const base::FilePath& directory) { +void TestOtherProcess(TestPaths::Architecture architecture) { ProcessInfo process_info; UUID done_uuid; @@ -142,15 +144,11 @@ CreateEvent(nullptr, true, false, done_uuid.ToString16().c_str())); ASSERT_TRUE(done.get()) << ErrorMessage("CreateEvent"); - std::wstring child_test_executable = - directory - .Append(TestPaths::Executable() - .BaseName() - .RemoveFinalExtension() - .value() + - L"_process_info_test_child.exe") - .value(); - + base::FilePath child_test_executable = + TestPaths::BuildArtifact(L"util", + L"process_info_test_child", + TestPaths::FileType::kExecutable, + architecture); std::wstring args; AppendCommandLineArgument(done_uuid.ToString16(), &args); @@ -191,17 +189,16 @@ } TEST(ProcessInfo, OtherProcess) { - TestOtherProcess(TestPaths::Executable().DirName()); + TestOtherProcess(TestPaths::Architecture::kDefault); } #if defined(ARCH_CPU_64_BITS) TEST(ProcessInfo, OtherProcessWOW64) { - base::FilePath output_32_bit_directory = TestPaths::Output32BitDirectory(); - if (output_32_bit_directory.empty()) { + if (!TestPaths::Has32BitBuildArtifacts()) { DISABLED_TEST(); } - TestOtherProcess(output_32_bit_directory); + TestOtherProcess(TestPaths::Architecture::k32Bit); } #endif // ARCH_CPU_64_BITS
diff --git a/third_party/crashpad/crashpad/util/win/safe_terminate_process_test.cc b/third_party/crashpad/crashpad/util/win/safe_terminate_process_test.cc index e3bfde7..3aba159 100644 --- a/third_party/crashpad/crashpad/util/win/safe_terminate_process_test.cc +++ b/third_party/crashpad/crashpad/util/win/safe_terminate_process_test.cc
@@ -163,14 +163,11 @@ } TEST(SafeTerminateProcess, TerminateChild) { - base::FilePath test_executable = TestPaths::Executable(); - std::wstring child_executable = - test_executable.DirName() - .Append(test_executable.BaseName().RemoveFinalExtension().value() + - L"_safe_terminate_process_test_child.exe") - .value(); - - ChildLauncher child(child_executable, std::wstring()); + base::FilePath child_executable = + TestPaths::BuildArtifact(L"util", + L"safe_terminate_process_test_child", + TestPaths::FileType::kExecutable); + ChildLauncher child(child_executable, L""); ASSERT_NO_FATAL_FAILURE(child.Start()); constexpr DWORD kExitCode = 0x51ee9d1e; // Sort of like “sleep and die.”
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium index 24eb91c..ecc31e8 100644 --- a/third_party/libvpx/README.chromium +++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@ License File: source/libvpx/LICENSE Security Critical: yes -Date: Wednesday October 18 2017 +Date: Wednesday November 01 2017 Branch: master -Commit: 401e6d48bfd3cbf74a41da724d05c989e207662b +Commit: 3ba9a2c8b2341430b001ed531f1eedf7c9b0384f Description: Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/libvpx_srcs.gni b/third_party/libvpx/libvpx_srcs.gni index c3eefa2..62ae7506 100644 --- a/third_party/libvpx/libvpx_srcs.gni +++ b/third_party/libvpx/libvpx_srcs.gni
@@ -460,6 +460,7 @@ ] libvpx_srcs_x86_avx2 = [ "//third_party/libvpx/source/libvpx/vp9/encoder/x86/vp9_error_avx2.c", + "//third_party/libvpx/source/libvpx/vpx_dsp/x86/avg_intrin_avx2.c", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/fwd_txfm_avx2.c", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_convolve_avx2.c", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/loopfilter_avx2.c", @@ -930,6 +931,7 @@ ] libvpx_srcs_x86_64_avx2 = [ "//third_party/libvpx/source/libvpx/vp9/encoder/x86/vp9_error_avx2.c", + "//third_party/libvpx/source/libvpx/vpx_dsp/x86/avg_intrin_avx2.c", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/fwd_txfm_avx2.c", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/highbd_convolve_avx2.c", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/loopfilter_avx2.c",
diff --git a/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h index 52c3d2c..3baa8752 100644 --- a/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/ios/arm-neon/vpx_dsp_rtcd.h
@@ -701,18 +701,18 @@ #define vpx_h_predictor_8x8 vpx_h_predictor_8x8_neon void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); void vpx_hadamard_16x16_neon(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_16x16 vpx_hadamard_16x16_neon void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); void vpx_hadamard_8x8_neon(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_8x8 vpx_hadamard_8x8_neon
diff --git a/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h index 52c3d2c..3baa8752 100644 --- a/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/ios/arm64/vpx_dsp_rtcd.h
@@ -701,18 +701,18 @@ #define vpx_h_predictor_8x8 vpx_h_predictor_8x8_neon void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); void vpx_hadamard_16x16_neon(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_16x16 vpx_hadamard_16x16_neon void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); void vpx_hadamard_8x8_neon(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_8x8 vpx_hadamard_8x8_neon
diff --git a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h index c6f4ef0..552d4f2 100644 --- a/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/arm-neon-cpu-detect/vpx_dsp_rtcd.h
@@ -901,23 +901,23 @@ const uint8_t* left); void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); void vpx_hadamard_16x16_neon(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); RTCD_EXTERN void (*vpx_hadamard_16x16)(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); void vpx_hadamard_8x8_neon(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); RTCD_EXTERN void (*vpx_hadamard_8x8)(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); void vpx_he_predictor_4x4_c(uint8_t* dst,
diff --git a/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h index 52c3d2c..3baa8752 100644 --- a/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/arm-neon/vpx_dsp_rtcd.h
@@ -701,18 +701,18 @@ #define vpx_h_predictor_8x8 vpx_h_predictor_8x8_neon void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); void vpx_hadamard_16x16_neon(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_16x16 vpx_hadamard_16x16_neon void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); void vpx_hadamard_8x8_neon(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_8x8 vpx_hadamard_8x8_neon
diff --git a/third_party/libvpx/source/config/linux/arm/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm/vpx_dsp_rtcd.h index 8afa3b7..ddd31b1b 100644 --- a/third_party/libvpx/source/config/linux/arm/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/arm/vpx_dsp_rtcd.h
@@ -466,12 +466,12 @@ #define vpx_h_predictor_8x8 vpx_h_predictor_8x8_c void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_16x16 vpx_hadamard_16x16_c void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_8x8 vpx_hadamard_8x8_c
diff --git a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h index 52c3d2c..3baa8752 100644 --- a/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/arm64/vpx_dsp_rtcd.h
@@ -701,18 +701,18 @@ #define vpx_h_predictor_8x8 vpx_h_predictor_8x8_neon void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); void vpx_hadamard_16x16_neon(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_16x16 vpx_hadamard_16x16_neon void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); void vpx_hadamard_8x8_neon(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_8x8 vpx_hadamard_8x8_neon
diff --git a/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h index 3f20ed8..474ce64 100644 --- a/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/generic/vpx_dsp_rtcd.h
@@ -466,12 +466,12 @@ #define vpx_h_predictor_8x8 vpx_h_predictor_8x8_c void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); #define vpx_hadamard_16x16 vpx_hadamard_16x16_c void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); #define vpx_hadamard_8x8 vpx_hadamard_8x8_c
diff --git a/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h index 0835030..61fd83d 100644 --- a/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
@@ -1089,23 +1089,26 @@ const uint8_t* left); void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_16x16_sse2(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, + tran_low_t* coeff); +void vpx_hadamard_16x16_avx2(const int16_t* src_diff, + ptrdiff_t src_stride, tran_low_t* coeff); RTCD_EXTERN void (*vpx_hadamard_16x16)(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_8x8_sse2(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); RTCD_EXTERN void (*vpx_hadamard_8x8)(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_he_predictor_4x4_c(uint8_t* dst, @@ -9012,6 +9015,8 @@ vpx_hadamard_16x16 = vpx_hadamard_16x16_c; if (flags & HAS_SSE2) vpx_hadamard_16x16 = vpx_hadamard_16x16_sse2; + if (flags & HAS_AVX2) + vpx_hadamard_16x16 = vpx_hadamard_16x16_avx2; vpx_hadamard_8x8 = vpx_hadamard_8x8_c; if (flags & HAS_SSE2) vpx_hadamard_8x8 = vpx_hadamard_8x8_sse2;
diff --git a/third_party/libvpx/source/config/linux/mips64el/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/mips64el/vpx_dsp_rtcd.h index a08da50..d628eab 100644 --- a/third_party/libvpx/source/config/linux/mips64el/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/mips64el/vpx_dsp_rtcd.h
@@ -466,12 +466,12 @@ #define vpx_h_predictor_8x8 vpx_h_predictor_8x8_c void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_16x16 vpx_hadamard_16x16_c void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_8x8 vpx_hadamard_8x8_c
diff --git a/third_party/libvpx/source/config/linux/mipsel/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/mipsel/vpx_dsp_rtcd.h index a08da50..d628eab 100644 --- a/third_party/libvpx/source/config/linux/mipsel/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/mipsel/vpx_dsp_rtcd.h
@@ -466,12 +466,12 @@ #define vpx_h_predictor_8x8 vpx_h_predictor_8x8_c void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_16x16 vpx_hadamard_16x16_c void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, int16_t* coeff); #define vpx_hadamard_8x8 vpx_hadamard_8x8_c
diff --git a/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h index 6e8baa8..f84e7cef 100644 --- a/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
@@ -972,24 +972,29 @@ #define vpx_h_predictor_8x8 vpx_h_predictor_8x8_sse2 void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_16x16_sse2(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); -#define vpx_hadamard_16x16 vpx_hadamard_16x16_sse2 +void vpx_hadamard_16x16_avx2(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); +RTCD_EXTERN void (*vpx_hadamard_16x16)(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_8x8_sse2(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_8x8_ssse3(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); RTCD_EXTERN void (*vpx_hadamard_8x8)(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_he_predictor_4x4_c(uint8_t* dst, @@ -7604,6 +7609,9 @@ vpx_get16x16var = vpx_get16x16var_sse2; if (flags & HAS_AVX2) vpx_get16x16var = vpx_get16x16var_avx2; + vpx_hadamard_16x16 = vpx_hadamard_16x16_sse2; + if (flags & HAS_AVX2) + vpx_hadamard_16x16 = vpx_hadamard_16x16_avx2; vpx_hadamard_8x8 = vpx_hadamard_8x8_sse2; if (flags & HAS_SSSE3) vpx_hadamard_8x8 = vpx_hadamard_8x8_ssse3;
diff --git a/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h index 0835030..61fd83d 100644 --- a/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
@@ -1089,23 +1089,26 @@ const uint8_t* left); void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_16x16_sse2(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, + tran_low_t* coeff); +void vpx_hadamard_16x16_avx2(const int16_t* src_diff, + ptrdiff_t src_stride, tran_low_t* coeff); RTCD_EXTERN void (*vpx_hadamard_16x16)(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_8x8_sse2(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); RTCD_EXTERN void (*vpx_hadamard_8x8)(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_he_predictor_4x4_c(uint8_t* dst, @@ -9012,6 +9015,8 @@ vpx_hadamard_16x16 = vpx_hadamard_16x16_c; if (flags & HAS_SSE2) vpx_hadamard_16x16 = vpx_hadamard_16x16_sse2; + if (flags & HAS_AVX2) + vpx_hadamard_16x16 = vpx_hadamard_16x16_avx2; vpx_hadamard_8x8 = vpx_hadamard_8x8_c; if (flags & HAS_SSE2) vpx_hadamard_8x8 = vpx_hadamard_8x8_sse2;
diff --git a/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h index 6e8baa8..f84e7cef 100644 --- a/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
@@ -972,24 +972,29 @@ #define vpx_h_predictor_8x8 vpx_h_predictor_8x8_sse2 void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_16x16_sse2(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); -#define vpx_hadamard_16x16 vpx_hadamard_16x16_sse2 +void vpx_hadamard_16x16_avx2(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); +RTCD_EXTERN void (*vpx_hadamard_16x16)(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_8x8_sse2(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_8x8_ssse3(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); RTCD_EXTERN void (*vpx_hadamard_8x8)(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_he_predictor_4x4_c(uint8_t* dst, @@ -7604,6 +7609,9 @@ vpx_get16x16var = vpx_get16x16var_sse2; if (flags & HAS_AVX2) vpx_get16x16var = vpx_get16x16var_avx2; + vpx_hadamard_16x16 = vpx_hadamard_16x16_sse2; + if (flags & HAS_AVX2) + vpx_hadamard_16x16 = vpx_hadamard_16x16_avx2; vpx_hadamard_8x8 = vpx_hadamard_8x8_sse2; if (flags & HAS_SSSE3) vpx_hadamard_8x8 = vpx_hadamard_8x8_ssse3;
diff --git a/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h index 3f20ed8..474ce64 100644 --- a/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/nacl/vpx_dsp_rtcd.h
@@ -466,12 +466,12 @@ #define vpx_h_predictor_8x8 vpx_h_predictor_8x8_c void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); #define vpx_hadamard_16x16 vpx_hadamard_16x16_c void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); #define vpx_hadamard_8x8 vpx_hadamard_8x8_c
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h index 5fb3a16c..acde048 100644 --- a/third_party/libvpx/source/config/vpx_version.h +++ b/third_party/libvpx/source/config/vpx_version.h
@@ -1,7 +1,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 6 #define VERSION_PATCH 1 -#define VERSION_EXTRA "1330-g401e6d48b" +#define VERSION_EXTRA "1352-g3ba9a2c8b" #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.6.1-1330-g401e6d48b" -#define VERSION_STRING " v1.6.1-1330-g401e6d48b" +#define VERSION_STRING_NOSP "v1.6.1-1352-g3ba9a2c8b" +#define VERSION_STRING " v1.6.1-1352-g3ba9a2c8b"
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h index 0835030..61fd83d 100644 --- a/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
@@ -1089,23 +1089,26 @@ const uint8_t* left); void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_16x16_sse2(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, + tran_low_t* coeff); +void vpx_hadamard_16x16_avx2(const int16_t* src_diff, + ptrdiff_t src_stride, tran_low_t* coeff); RTCD_EXTERN void (*vpx_hadamard_16x16)(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_8x8_sse2(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); RTCD_EXTERN void (*vpx_hadamard_8x8)(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_he_predictor_4x4_c(uint8_t* dst, @@ -9012,6 +9015,8 @@ vpx_hadamard_16x16 = vpx_hadamard_16x16_c; if (flags & HAS_SSE2) vpx_hadamard_16x16 = vpx_hadamard_16x16_sse2; + if (flags & HAS_AVX2) + vpx_hadamard_16x16 = vpx_hadamard_16x16_avx2; vpx_hadamard_8x8 = vpx_hadamard_8x8_c; if (flags & HAS_SSE2) vpx_hadamard_8x8 = vpx_hadamard_8x8_sse2;
diff --git a/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h index 6e8baa8..f84e7cef 100644 --- a/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
@@ -972,24 +972,29 @@ #define vpx_h_predictor_8x8 vpx_h_predictor_8x8_sse2 void vpx_hadamard_16x16_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_16x16_sse2(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); -#define vpx_hadamard_16x16 vpx_hadamard_16x16_sse2 +void vpx_hadamard_16x16_avx2(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); +RTCD_EXTERN void (*vpx_hadamard_16x16)(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); void vpx_hadamard_8x8_c(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_8x8_sse2(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_hadamard_8x8_ssse3(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); RTCD_EXTERN void (*vpx_hadamard_8x8)(const int16_t* src_diff, - int src_stride, + ptrdiff_t src_stride, tran_low_t* coeff); void vpx_he_predictor_4x4_c(uint8_t* dst, @@ -7604,6 +7609,9 @@ vpx_get16x16var = vpx_get16x16var_sse2; if (flags & HAS_AVX2) vpx_get16x16var = vpx_get16x16var_avx2; + vpx_hadamard_16x16 = vpx_hadamard_16x16_sse2; + if (flags & HAS_AVX2) + vpx_hadamard_16x16 = vpx_hadamard_16x16_avx2; vpx_hadamard_8x8 = vpx_hadamard_8x8_sse2; if (flags & HAS_SSSE3) vpx_hadamard_8x8 = vpx_hadamard_8x8_ssse3;
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py index 0068fb7..d0106cef 100644 --- a/tools/binary_size/libsupersize/archive.py +++ b/tools/binary_size/libsupersize/archive.py
@@ -388,7 +388,10 @@ logging.debug('Created %d string literal symbols', sum(len(x) for x in ret)) logging.debug('Sorting string literals') for symbols in ret: - symbols.sort(key=lambda x: (x.address, -x.size)) + # In order to achieve a total ordering in the presense of aliases, need to + # include both |address| and |object_path|. + # In order to achieve consistent deduping, need to include |size|. + symbols.sort(key=lambda x: (x.address, -x.size, x.object_path)) logging.debug('Deduping string literals') num_removed = 0
diff --git a/tools/binary_size/libsupersize/integration_test.py b/tools/binary_size/libsupersize/integration_test.py index 7ecdf44..b427c10 100755 --- a/tools/binary_size/libsupersize/integration_test.py +++ b/tools/binary_size/libsupersize/integration_test.py
@@ -113,19 +113,25 @@ output_directory) return copy.deepcopy(IntegrationTest.cached_size_info[i]) + def _DoArchive(self, archive_path, use_output_directory=True, use_elf=True, + debug_measures=False): + args = [archive_path, '--map-file', _TEST_MAP_PATH] + if use_output_directory: + # Let autodetection find output_directory when --elf-file is used. + if not use_elf: + args += ['--output-directory', _TEST_OUTPUT_DIR] + else: + args += ['--no-source-paths'] + if use_elf: + args += ['--elf-file', _TEST_ELF_PATH] + _RunApp('archive', args, debug_measures=debug_measures) + def _DoArchiveTest(self, use_output_directory=True, use_elf=True, debug_measures=False): with tempfile.NamedTemporaryFile(suffix='.size') as temp_file: - args = [temp_file.name, '--map-file', _TEST_MAP_PATH] - if use_output_directory: - # Let autodetection find output_directory when --elf-file is used. - if not use_elf: - args += ['--output-directory', _TEST_OUTPUT_DIR] - else: - args += ['--no-source-paths'] - if use_elf: - args += ['--elf-file', _TEST_ELF_PATH] - _RunApp('archive', args, debug_measures=debug_measures) + self._DoArchive( + temp_file.name, use_output_directory=use_output_directory, + use_elf=use_elf, debug_measures=debug_measures) size_info = archive.LoadAndPostProcessSizeInfo(temp_file.name) # Check that saving & loading is the same as directly parsing the .map. expected_size_info = self._CloneSizeInfo( @@ -200,6 +206,16 @@ file_format.SaveSizeInfo(self._CloneSizeInfo(), temp_file.name) return _RunApp('diff', [temp_file.name, temp_file.name]) + # Runs archive 3 times, and asserts the contents are the same each time. + def test_Idempotent(self): + prev_contents = None + for _ in xrange(3): + with tempfile.NamedTemporaryFile(suffix='.size') as temp_file: + self._DoArchive(temp_file.name) + contents = temp_file.read() + self.assertTrue(prev_contents is None or contents == prev_contents) + prev_contents = contents + @_CompareWithGolden() def test_Diff_Basic(self): size_info1 = self._CloneSizeInfo(use_elf=False)
diff --git a/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_readelf.py b/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_readelf.py index 23ac20a..1e1f006 100644 --- a/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_readelf.py +++ b/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_readelf.py
@@ -150,10 +150,7 @@ Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 - -Section Headers: - [Nr] Name Type Addr Off Size ES Flg Lk Inf Al - [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .rodata.str1.1 PROGBITS 00000000 000015 000005 01 AMS 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) @@ -165,10 +162,6 @@ Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 - -Section Headers: - [Nr] Name Type Addr Off Size ES Flg Lk Inf Al - [ 0] NULL 00000000 000000 000000 00 0 0 0 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) @@ -183,10 +176,6 @@ Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 - -Section Headers: - [Nr] Name Type Addr Off Size ES Flg Lk Inf Al - [ 0] NULL 00000000 000000 000000 00 0 0 0 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) @@ -199,10 +188,6 @@ Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 - -Section Headers: - [Nr] Name Type Addr Off Size ES Flg Lk Inf Al - [ 0] NULL 00000000 000000 000000 00 0 0 0 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
diff --git a/tools/clang/scripts/package.py b/tools/clang/scripts/package.py index fb3c866..af0456c 100755 --- a/tools/clang/scripts/package.py +++ b/tools/clang/scripts/package.py
@@ -93,9 +93,7 @@ def MaybeUpload(args, archive_name, platform): - # We don't want to rewrite the file, if it already exists on the server, - # so -n option to gsutil is used. It will warn, if the upload was aborted. - gsutil_args = ['cp', '-n', '-a', 'public-read', + gsutil_args = ['cp', '-a', 'public-read', '%s.tgz' % archive_name, 'gs://chromium-browser-clang-staging/%s/%s.tgz' % (platform, archive_name)] @@ -183,13 +181,6 @@ else: platform = 'Linux_x64' - # Check if Google Cloud Storage already has the artifacts we want to build. - if args.upload and GsutilArchiveExists(pdir, platform): - print ('Desired toolchain revision %s is already available ' - 'in Google Cloud Storage:') % expected_stamp - print 'gs://chromium-browser-clang-staging/%s/%s.tgz' % (platform, pdir) - return 0 - with open('buildlog.txt', 'w') as log: Tee('Diff in llvm:\n', log) TeeCmd(['svn', 'stat', LLVM_DIR], log, fail_hard=False)
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index df9722b..ee18e1e 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -539,7 +539,6 @@ 'android_clang_dbg_recipe': 'android_clang_asan_errorprone_findbugs_debug_trybot', 'android_compile_dbg': 'android_debug_trybot', 'android_compile_mips_dbg': 'android_debug_trybot_mipsel', - 'android_compile_rel': 'android_release_trybot', 'android_compile_x64_dbg': 'android_debug_trybot_x64', 'android_compile_x86_dbg': 'android_debug_trybot_x86', 'android_coverage': 'android_debug_trybot_java_coverage',
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 320c3e7..5ff09a1 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -91633,6 +91633,17 @@ </summary> </histogram> +<histogram name="WebApk.Update.NumStaleUpdateRequestFiles" units="files"> + <owner>hanxi@chromium.org</owner> + <owner>pkotwicz@chromium.org</owner> + <owner>yfriedman@chromium.org</owner> + <summary> + Records the number of zombie "WebAPK update request" files that + the update process failed to cleanup. Recorded for all WebAPKs whenever a + WebAPK or webapp is launched. + </summary> +</histogram> + <histogram name="WebApk.Update.RequestQueued" enum="WebApkUpdateRequestQueued"> <owner>hanxi@chromium.org</owner> <owner>pkotwicz@chromium.org</owner>
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc index dc7f1c6..71296ec 100644 --- a/ui/keyboard/keyboard_controller.cc +++ b/ui/keyboard/keyboard_controller.cc
@@ -166,47 +166,30 @@ // Observer for both keyboard show and hide animations. It should be owned by // KeyboardController. -class CallbackAnimationObserver : public ui::LayerAnimationObserver { +class CallbackAnimationObserver : public ui::ImplicitAnimationObserver { public: - CallbackAnimationObserver(const scoped_refptr<ui::LayerAnimator>& animator, - base::OnceCallback<void(void)> callback); - ~CallbackAnimationObserver() override; + CallbackAnimationObserver(base::OnceClosure callback) + : callback_(std::move(callback)) {} private: - // Overridden from ui::LayerAnimationObserver: - void OnLayerAnimationEnded(ui::LayerAnimationSequence* seq) override; - void OnLayerAnimationAborted(ui::LayerAnimationSequence* seq) override; - void OnLayerAnimationScheduled(ui::LayerAnimationSequence* seq) override {} + // ui::ImplicitAnimationObserver: + void OnImplicitAnimationsCompleted() override { + if (WasAnimationAbortedForProperty(ui::LayerAnimationElement::TRANSFORM) || + WasAnimationAbortedForProperty(ui::LayerAnimationElement::OPACITY)) { + return; + } + DCHECK( + WasAnimationCompletedForProperty(ui::LayerAnimationElement::TRANSFORM)); + DCHECK( + WasAnimationCompletedForProperty(ui::LayerAnimationElement::OPACITY)); + std::move(callback_).Run(); + } - scoped_refptr<ui::LayerAnimator> animator_; - base::OnceCallback<void(void)> callback_; + base::OnceClosure callback_; DISALLOW_COPY_AND_ASSIGN(CallbackAnimationObserver); }; -CallbackAnimationObserver::CallbackAnimationObserver( - const scoped_refptr<ui::LayerAnimator>& animator, - base::OnceCallback<void(void)> callback) - : animator_(animator), callback_(std::move(callback)) {} - -CallbackAnimationObserver::~CallbackAnimationObserver() { - animator_->RemoveObserver(this); -} - -void CallbackAnimationObserver::OnLayerAnimationEnded( - ui::LayerAnimationSequence* seq) { - if (animator_->is_animating()) - return; - animator_->RemoveObserver(this); - DCHECK(!callback_.is_null()); - std::move(callback_).Run(); -} - -void CallbackAnimationObserver::OnLayerAnimationAborted( - ui::LayerAnimationSequence* seq) { - animator_->RemoveObserver(this); -} - // static KeyboardController* KeyboardController::instance_ = NULL; @@ -367,13 +350,12 @@ set_keyboard_locked(false); - ui::LayerAnimator* container_animator = - container_->layer()->GetAnimator(); - animation_observer_.reset(new CallbackAnimationObserver( - container_animator, + animation_observer_ = std::make_unique<CallbackAnimationObserver>( base::BindOnce(&KeyboardController::HideAnimationFinished, - base::Unretained(this)))); - container_animator->AddObserver(animation_observer_.get()); + base::Unretained(this))); + ui::ScopedLayerAnimationSettings layer_animation_settings( + container_->layer()->GetAnimator()); + layer_animation_settings.AddObserver(animation_observer_.get()); aura::Window* window = container_.get(); @@ -625,15 +607,12 @@ container_animator->set_preemption_strategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - animation_observer_.reset(new CallbackAnimationObserver( - container_animator, - base::BindOnce(&KeyboardController::ShowAnimationFinished, - base::Unretained(this)))); - container_animator->AddObserver(animation_observer_.get()); - ui_->ShowKeyboardContainer(container_.get()); + animation_observer_ = std::make_unique<CallbackAnimationObserver>( + base::BindOnce(&MarkKeyboardLoadFinished)); ui::ScopedLayerAnimationSettings settings(container_animator); + settings.AddObserver(animation_observer_.get()); container_behavior_->DoShowingAnimation(container_.get(), &settings); @@ -647,10 +626,6 @@ return res; } -void KeyboardController::ShowAnimationFinished() { - MarkKeyboardLoadFinished(); -} - void KeyboardController:: NotifyKeyboardBoundsChangingAndEnsureCaretInWorkArea() { // Notify observers after animation finished to prevent reveal desktop
diff --git a/ui/keyboard/keyboard_controller.h b/ui/keyboard/keyboard_controller.h index 9d38a7a26..f873899 100644 --- a/ui/keyboard/keyboard_controller.h +++ b/ui/keyboard/keyboard_controller.h
@@ -203,9 +203,7 @@ // Returns true if keyboard is scheduled to hide. bool WillHideKeyboard() const; - // Called when show and hide animation finished successfully. If the animation - // is aborted, it won't be called. - void ShowAnimationFinished(); + // Called when the hide animation finishes. void HideAnimationFinished(); void NotifyKeyboardBoundsChangingAndEnsureCaretInWorkArea();