diff --git a/BUILD.gn b/BUILD.gn index 375462b..4e5a0226 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -658,10 +658,10 @@ "//chrome/installer/util:strings", "//chrome/tools/convert_dict", "//components/constrained_window:unit_tests", - "//components/filesystem:filesystem_service_unittests", - "//components/leveldb:leveldb_service_unittests", "//components/metrics:serialization", "//components/rappor:unit_tests", + "//components/services/filesystem:filesystem_service_unittests", + "//components/services/leveldb:leveldb_service_unittests", "//components/sessions:unit_tests", "//media/blink:media_blink_unittests", "//media/cast:udp_proxy",
diff --git a/DEPS b/DEPS index 30e40ade..c85fd5c 100644 --- a/DEPS +++ b/DEPS
@@ -79,11 +79,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'c25e2693ab00cfe7691b68b7d47f2159640d783a', + 'skia_revision': 'fd6ed022db18d7e1b48a544f4e0f0dbf6ef206b6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '21cb7e30e4995fe0602963da903bdc84de78a82a', + 'v8_revision': '5018e7b89920ff8b9deff450fa25fec1e4e05f4c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -91,7 +91,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '64e5ed2abd8a4cc77d3647e4b245db57a8c42ae5', + 'angle_revision': 'f0b30dd8bd2bd68d6aad0e161f5fc3816d5a5077', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -103,7 +103,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': '0c6b98182403868334b4dfe4852caa4d0e2ba272', + 'pdfium_revision': '7a1aa5f659110e99950b00b6b326b41436872635', # 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. @@ -341,7 +341,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'f4c2703a6dedd8aed2d00fd7b57a6adf579271d9', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '68de9f34db445a1371a421cc0fa6b9480bd9a853', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -657,7 +657,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '3c1cb0203b6cfc10389e85a350b2ea6ca29d01ce', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '207a75d8f3fae1dc47aa20dda0636e88f6b8d2b3', # commit position 21742 + Var('webrtc_git') + '/src.git' + '@' + '3133857266925d4bc66e0bddef8c9a1fefc3a060', # commit position 21742 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/OWNERS b/OWNERS index db7e31d..1988231 100644 --- a/OWNERS +++ b/OWNERS
@@ -19,6 +19,7 @@ per-file codereview.settings=agable@chromium.org per-file DEPS=* per-file PRESUBMIT*.py=dcheng@chromium.org +per-file PRESUBMIT*.py=dpranke@chromium.org per-file PRESUBMIT*.py=jochen@chromium.org per-file README.md=* per-file WATCHLISTS=*
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 6e30749..482790ad 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -556,8 +556,8 @@ # Bypass the AUTHORS check for these accounts. _KNOWN_ROBOTS = set( '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s - for s in ('afdo', 'angle', 'catapult', 'depot-tools', 'nacl', 'pdfium', - 'skia', 'src-internal', 'webrtc')) + for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools', 'nacl', + 'pdfium', 'skia', 'src-internal', 'webrtc')) def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
diff --git a/WATCHLISTS b/WATCHLISTS index 2f95b4be..3cc62e2 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -62,6 +62,10 @@ '|media/midi/*_android.*' \ '|media/video/capture/android' }, + 'android_search_widget': { + 'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/locale/' \ + '|chrome/android/java/src/org/chromium/chrome/browser/searchwidget/' + }, 'android_studio': { 'filepath': 'build/android/gradle/' \ '|docs/android_studio.md' \ @@ -1649,6 +1653,8 @@ 'android_loading': ['gabadie+watch@chromium.org', 'lizeb+watch-android-loading@chromium.org'], 'android_media': ['mlamouri+watch-media@chromium.org'], + 'android_search_widget': ['tedchoc+watch@chromium.org', + 'yusufo+watch@chromium.org'], 'android_studio': ['wnwen+watch@chromium.org', 'nyquist+watch@chromium.org'], 'android_tab': ['dtrainor+watch@chromium.org'],
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index b924567a..2189f9c6 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -205,6 +205,8 @@ "frame/frame_border_hit_test.cc", "frame/frame_border_hit_test.h", "frame/frame_header.h", + "frame/frame_header_origin_text.cc", + "frame/frame_header_origin_text.h", "frame/frame_header_util.cc", "frame/frame_header_util.h", "frame/header_view.cc",
diff --git a/ash/frame/frame_header_origin_text.cc b/ash/frame/frame_header_origin_text.cc new file mode 100644 index 0000000..4dc15a3 --- /dev/null +++ b/ash/frame/frame_header_origin_text.cc
@@ -0,0 +1,114 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/frame/frame_header_origin_text.h" + +#include "base/i18n/rtl.h" +#include "ui/compositor/layer_animation_element.h" +#include "ui/compositor/layer_animation_sequence.h" +#include "ui/compositor/scoped_layer_animation_settings.h" +#include "ui/views/controls/label.h" +#include "ui/views/layout/fill_layout.h" + +namespace ash { + +namespace { + +constexpr base::TimeDelta kOriginSlideInDuration = + base::TimeDelta::FromMilliseconds(800); +constexpr base::TimeDelta kOriginPauseDuration = + base::TimeDelta::FromMilliseconds(2500); +constexpr base::TimeDelta kOriginSlideOutDuration = + base::TimeDelta::FromMilliseconds(500); + +constexpr gfx::Tween::Type kTweenType = gfx::Tween::FAST_OUT_SLOW_IN_2; + +} // namespace + +FrameHeaderOriginText::FrameHeaderOriginText(const base::string16& origin, + SkColor active_color, + SkColor inactive_color, + SkColor active_background_color, + SkColor inactive_background_color) + : active_color_(active_color), + inactive_color_(inactive_color), + active_background_color_(active_background_color), + inactive_background_color_(inactive_background_color) { + SetLayoutManager(std::make_unique<views::FillLayout>()); + + label_ = std::make_unique<views::Label>(origin).release(); + label_->SetElideBehavior(gfx::ELIDE_HEAD); + label_->SetSubpixelRenderingEnabled(false); + label_->SetEnabledColor(active_color); + label_->SetBackgroundColor(active_background_color); + label_->SetPaintToLayer(); + label_->layer()->SetFillsBoundsOpaquely(false); + label_->layer()->SetOpacity(0); + AddChildView(label_); + + // Clip child views to this view. + SetPaintToLayer(); + layer()->SetFillsBoundsOpaquely(false); + layer()->SetMasksToBounds(true); +} + +FrameHeaderOriginText::~FrameHeaderOriginText() = default; + +void FrameHeaderOriginText::SetPaintAsActive(bool active) { + label_->SetEnabledColor(active ? active_color_ : inactive_color_); + label_->SetBackgroundColor(active ? active_background_color_ + : inactive_background_color_); +} + +void FrameHeaderOriginText::StartSlideAnimation() { + ui::Layer* label_layer = label_->layer(); + + // Current state will become the first animation keyframe. + DCHECK_EQ(label_layer->opacity(), 0); + gfx::Transform out_of_frame; + out_of_frame.Translate( + label_->bounds().width() * (base::i18n::IsRTL() ? -1 : 1), 0); + label_layer->SetTransform(out_of_frame); + + auto opacity_sequence = std::make_unique<ui::LayerAnimationSequence>(); + auto transform_sequence = std::make_unique<ui::LayerAnimationSequence>(); + + // Slide in. + auto opacity_keyframe = ui::LayerAnimationElement::CreateOpacityElement( + 1, kOriginSlideInDuration); + opacity_keyframe->set_tween_type(kTweenType); + opacity_sequence->AddElement(std::move(opacity_keyframe)); + + auto transform_keyframe = ui::LayerAnimationElement::CreateTransformElement( + gfx::Transform(), kOriginSlideInDuration); + transform_keyframe->set_tween_type(kTweenType); + transform_sequence->AddElement(std::move(transform_keyframe)); + + // Pause. + opacity_sequence->AddElement( + ui::LayerAnimationElement::CreatePauseElement(0, kOriginPauseDuration)); + transform_sequence->AddElement( + ui::LayerAnimationElement::CreatePauseElement(0, kOriginPauseDuration)); + + // Slide out. + opacity_keyframe = ui::LayerAnimationElement::CreateOpacityElement( + 0, kOriginSlideOutDuration); + opacity_keyframe->set_tween_type(kTweenType); + opacity_sequence->AddElement(std::move(opacity_keyframe)); + + transform_keyframe = ui::LayerAnimationElement::CreateTransformElement( + out_of_frame, kOriginSlideOutDuration); + transform_keyframe->set_tween_type(kTweenType); + transform_sequence->AddElement(std::move(transform_keyframe)); + + label_layer->GetAnimator()->StartTogether( + {opacity_sequence.release(), transform_sequence.release()}); +} + +base::TimeDelta FrameHeaderOriginText::AnimationDuration() { + return kOriginSlideInDuration + kOriginPauseDuration + + kOriginSlideOutDuration; +} + +} // namespace ash
diff --git a/ash/frame/frame_header_origin_text.h b/ash/frame/frame_header_origin_text.h new file mode 100644 index 0000000..9b3b9cd --- /dev/null +++ b/ash/frame/frame_header_origin_text.h
@@ -0,0 +1,53 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_FRAME_FRAME_HEADER_ORIGIN_TEXT_H_ +#define ASH_FRAME_FRAME_HEADER_ORIGIN_TEXT_H_ + +#include "ash/ash_export.h" +#include "base/strings/string16.h" +#include "base/time/time.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/views/view.h" + +namespace views { +class Label; +} + +namespace ash { + +// A URL's origin text with a slide in/out animation. +class ASH_EXPORT FrameHeaderOriginText : public views::View { + public: + FrameHeaderOriginText(const base::string16& origin, + SkColor active_color, + SkColor inactive_color, + SkColor active_background_color, + SkColor inactive_background_color); + ~FrameHeaderOriginText() override; + + // Sets whether to paint the text with the active/inactive color. + void SetPaintAsActive(bool active); + + // Slides the text in and out. + void StartSlideAnimation(); + + // How long the slide in+out animation takes. + static base::TimeDelta AnimationDuration(); + + private: + // Owned by the views hierarchy. + views::Label* label_ = nullptr; + + const SkColor active_color_; + const SkColor inactive_color_; + const SkColor active_background_color_; + const SkColor inactive_background_color_; + + DISALLOW_COPY_AND_ASSIGN(FrameHeaderOriginText); +}; + +} // namespace ash + +#endif // ASH_FRAME_FRAME_HEADER_ORIGIN_TEXT_H_
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc index fe2ef454..8a67242e 100644 --- a/ash/wm/overview/window_selector_unittest.cc +++ b/ash/wm/overview/window_selector_unittest.cc
@@ -66,20 +66,19 @@ #include "ui/gfx/transform_util.h" #include "ui/wm/core/coordinate_conversion.h" #include "ui/wm/core/window_util.h" -#include "ui/wm/public/activation_delegate.h" namespace ash { namespace { // The label covers selector item windows with a padding in order to prevent // them from receiving user input events while in overview. -static const int kWindowMargin = 5; +constexpr int kWindowMargin = 5; // The overview mode header overlaps original window header. This value is used // to set top inset property on the windows. -static const int kHeaderHeight = 32; +constexpr int kHeaderHeight = 32; -const char kActiveWindowChangedFromOverview[] = +constexpr const char kActiveWindowChangedFromOverview[] = "WindowSelector_ActiveWindowChanged"; // A simple window delegate that returns the specified hit-test code when @@ -96,11 +95,6 @@ DISALLOW_COPY_AND_ASSIGN(TestDragWindowDelegate); }; -class NonActivatableActivationDelegate : public ::wm::ActivationDelegate { - public: - bool ShouldActivate() const override { return false; } -}; - float GetItemScale(const gfx::Rect& source, const gfx::Rect& target, int top_view_inset, @@ -121,9 +115,9 @@ void SetUp() override { AshTestBase::SetUp(); - shelf_view_test_.reset( - new ShelfViewTestAPI(GetPrimaryShelf()->GetShelfViewForTesting())); - shelf_view_test_->SetAnimationDuration(1); + shelf_view_test_api_ = std::make_unique<ShelfViewTestAPI>( + GetPrimaryShelf()->GetShelfViewForTesting()); + shelf_view_test_api_->SetAnimationDuration(1); ScopedTransformOverviewWindow::SetImmediateCloseForTests(); } @@ -147,12 +141,6 @@ window->SetProperty(aura::client::kTopViewInset, kHeaderHeight); return window; } - aura::Window* CreateNonActivatableWindow(const gfx::Rect& bounds) { - aura::Window* window = CreateWindow(bounds); - ::wm::SetActivationDelegate(window, &non_activatable_activation_delegate_); - EXPECT_FALSE(wm::CanActivateWindow(window)); - return window; - } // Creates a Widget containing a Window with the given |bounds|. This should // be used when the test requires a Widget. For example any test that will @@ -180,7 +168,7 @@ window->SetProperty(kShelfIDKey, new std::string(shelf_id)); window->SetProperty<int>(kShelfItemTypeKey, TYPE_APP_PANEL); window->SetProperty(aura::client::kTopViewInset, kHeaderHeight); - shelf_view_test()->RunMessageLoopUntilAnimationsDone(); + shelf_view_test_api_->RunMessageLoopUntilAnimationsDone(); return window; } @@ -246,18 +234,10 @@ event_generator.ClickLeftButton(); } - void SendKey(ui::KeyboardCode key) { + void SendKey(ui::KeyboardCode key, int flags = ui::EF_NONE) { ui::test::EventGenerator event_generator(Shell::GetPrimaryRootWindow()); - event_generator.PressKey(key, 0); - event_generator.ReleaseKey(key, 0); - } - - void SendCtrlKey(ui::KeyboardCode key) { - ui::test::EventGenerator event_generator(Shell::GetPrimaryRootWindow()); - event_generator.PressKey(ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN); - event_generator.PressKey(key, ui::EF_CONTROL_DOWN); - event_generator.ReleaseKey(key, ui::EF_CONTROL_DOWN); - event_generator.ReleaseKey(ui::VKEY_CONTROL, ui::EF_NONE); + event_generator.PressKey(key, flags); + event_generator.ReleaseKey(key, flags); } bool IsSelecting() { return window_selector_controller()->IsSelecting(); } @@ -352,8 +332,6 @@ window_selector()->ContentsChanged(nullptr, base::UTF8ToUTF16(pattern)); } - ShelfViewTestAPI* shelf_view_test() { return shelf_view_test_.get(); } - views::Widget* text_filter_widget() { return window_selector()->text_filter_widget_.get(); } @@ -365,11 +343,6 @@ return gfx::Rect(); } - OverviewWindowDragController* window_drag_controller() { - DCHECK(window_selector()); - return window_selector()->window_drag_controller_.get(); - } - views::Widget* item_widget(WindowSelectorItem* item) { return item->item_widget_.get(); } @@ -388,8 +361,7 @@ private: aura::test::TestWindowDelegate delegate_; - NonActivatableActivationDelegate non_activatable_activation_delegate_; - std::unique_ptr<ShelfViewTestAPI> shelf_view_test_; + std::unique_ptr<ShelfViewTestAPI> shelf_view_test_api_; DISALLOW_COPY_AND_ASSIGN(WindowSelectorTest); }; @@ -397,9 +369,9 @@ // Tests that the text field in the overview menu is repositioned and resized // after a screen rotation. TEST_F(WindowSelectorTest, OverviewScreenRotation) { - gfx::Rect bounds(0, 0, 400, 300); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - std::unique_ptr<aura::Window> panel1(CreatePanelWindow(bounds)); + const gfx::Rect bounds(400, 300); + std::unique_ptr<aura::Window> window(CreateWindow(bounds)); + std::unique_ptr<aura::Window> panel(CreatePanelWindow(bounds)); // In overview mode the windows should no longer overlap and the text filter // widget should be focused. @@ -415,8 +387,7 @@ // w: std::min(kTextFilterWidth, total_bounds.width()). // h: kTextFilterHeight. gfx::Rect expected_bounds(60, -42, 280, 40); - EXPECT_EQ(expected_bounds.ToString(), - text_filter->GetClientAreaBoundsInScreen().ToString()); + EXPECT_EQ(expected_bounds, text_filter->GetClientAreaBoundsInScreen()); // Rotates the display, which triggers the WindowSelector's // RepositionTextFilterOnDisplayMetricsChange method. @@ -424,18 +395,17 @@ // Uses the same formulas as above using width = 300, height = 400. expected_bounds = gfx::Rect(10, -42, 280, 40); - EXPECT_EQ(expected_bounds.ToString(), - text_filter->GetClientAreaBoundsInScreen().ToString()); + EXPECT_EQ(expected_bounds, text_filter->GetClientAreaBoundsInScreen()); } // Tests that an a11y alert is sent on entering overview mode. TEST_F(WindowSelectorTest, A11yAlertOnOverviewMode) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); TestAccessibilityControllerClient client; AccessibilityController* controller = Shell::Get()->accessibility_controller(); controller->SetClient(client.CreateInterfacePtrAndBind()); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window(CreateWindow(bounds)); EXPECT_NE(mojom::AccessibilityAlert::WINDOW_OVERVIEW_MODE_ENTERED, client.last_a11y_alert()); ToggleOverview(); @@ -462,7 +432,7 @@ // Tests entering overview mode with two windows and selecting one by clicking. TEST_F(WindowSelectorTest, Basic) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); aura::Window* root_window = Shell::GetPrimaryRootWindow(); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); @@ -504,7 +474,7 @@ // Tests activating minimized window. TEST_F(WindowSelectorTest, ActivateMinimized) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window(CreateWindow(bounds)); wm::WindowState* window_state = wm::GetWindowState(window.get()); @@ -540,12 +510,12 @@ // Tests that entering overview mode with an App-list active properly focuses // and activates the overview text filter window. TEST_F(WindowSelectorTest, TextFilterActive) { - gfx::Rect bounds(0, 0, 400, 400); - std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); - wm::ActivateWindow(window1.get()); + const gfx::Rect bounds(400, 400); + std::unique_ptr<aura::Window> window(CreateWindow(bounds)); + wm::ActivateWindow(window.get()); - EXPECT_TRUE(wm::IsActiveWindow(window1.get())); - EXPECT_EQ(window1.get(), wm::GetFocusedWindow()); + EXPECT_TRUE(wm::IsActiveWindow(window.get())); + EXPECT_EQ(window.get(), wm::GetFocusedWindow()); // Pass an enum to satisfy the function, it is arbitrary and will not affect // histograms. @@ -556,7 +526,7 @@ // previously active |window1|. Overview mode should properly transfer focus // and activation to the text filter widget. ToggleOverview(); - EXPECT_FALSE(wm::IsActiveWindow(window1.get())); + EXPECT_FALSE(wm::IsActiveWindow(window.get())); EXPECT_TRUE(wm::IsActiveWindow(wm::GetFocusedWindow())); EXPECT_EQ(text_filter_widget()->GetNativeWindow(), wm::GetFocusedWindow()); } @@ -564,7 +534,7 @@ // Tests that the ordering of windows is stable across different overview // sessions even when the windows have the same bounds. TEST_F(WindowSelectorTest, WindowsOrder) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindowWithId(bounds, 1)); std::unique_ptr<aura::Window> window2(CreateWindowWithId(bounds, 2)); std::unique_ptr<aura::Window> window3(CreateWindowWithId(bounds, 3)); @@ -594,7 +564,7 @@ // Tests selecting a window by tapping on it. TEST_F(WindowSelectorTest, BasicGesture) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); wm::ActivateWindow(window1.get()); @@ -613,7 +583,7 @@ // in overview mode which is different from the previously-active window. TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionRecorded) { base::UserActionTester user_action_tester; - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); @@ -650,7 +620,7 @@ // exiting overview without selecting a window does not record the action. TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionNotRecorded) { base::UserActionTester user_action_tester; - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); @@ -694,7 +664,7 @@ TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionWindowClose) { base::UserActionTester user_action_tester; std::unique_ptr<views::Widget> widget = - CreateWindowWidget(gfx::Rect(0, 0, 400, 400)); + CreateWindowWidget(gfx::Rect(400, 400)); ToggleOverview(); @@ -737,7 +707,7 @@ // Tests that we do not crash and a window is selected when appropriate when // we click on a window during touch. TEST_F(WindowSelectorTest, ClickOnWindowDuringTouch) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); wm::ActivateWindow(window2.get()); @@ -849,7 +819,7 @@ // Tests minimizing/unminimizing in overview mode. TEST_F(WindowSelectorTest, MinimizeUnminimize) { std::unique_ptr<views::Widget> widget = - CreateWindowWidget(gfx::Rect(0, 0, 400, 400)); + CreateWindowWidget(gfx::Rect(400, 400)); aura::Window* window = widget->GetNativeWindow(); ToggleOverview(); @@ -907,7 +877,7 @@ // Tests entering overview mode with two windows and selecting one. TEST_F(WindowSelectorTest, FullscreenWindow) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); std::unique_ptr<aura::Window> panel1(CreatePanelWindow(bounds)); @@ -941,7 +911,7 @@ } TEST_F(WindowSelectorTest, SkipOverviewWindow) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); @@ -964,7 +934,7 @@ // mode correctly applies the transformations to the window and correctly // updates the window bounds on exiting overview mode: http://crbug.com/401664. TEST_F(WindowSelectorTest, FullscreenWindowTabletMode) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); @@ -974,34 +944,29 @@ const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN); wm::GetWindowState(window1.get())->OnWMEvent(&toggle_fullscreen_event); gfx::Rect fullscreen_window_bounds(window1->bounds()); - EXPECT_NE(normal_window_bounds.ToString(), - fullscreen_window_bounds.ToString()); - EXPECT_EQ(fullscreen_window_bounds.ToString(), - window2->GetTargetBounds().ToString()); + EXPECT_NE(normal_window_bounds, fullscreen_window_bounds); + EXPECT_EQ(fullscreen_window_bounds, window2->GetTargetBounds()); ToggleOverview(); // Window 2 would normally resize to normal window bounds on showing the shelf // for overview but this is deferred until overview is exited. - EXPECT_EQ(fullscreen_window_bounds.ToString(), - window2->GetTargetBounds().ToString()); + EXPECT_EQ(fullscreen_window_bounds, window2->GetTargetBounds()); EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get())); ToggleOverview(); // Since the fullscreen window is still active, window2 will still have the // larger bounds. - EXPECT_EQ(fullscreen_window_bounds.ToString(), - window2->GetTargetBounds().ToString()); + EXPECT_EQ(fullscreen_window_bounds, window2->GetTargetBounds()); // Enter overview again and select window 2. Selecting window 2 should show // the shelf bringing window2 back to the normal bounds. ToggleOverview(); ClickWindow(window2.get()); - EXPECT_EQ(normal_window_bounds.ToString(), - window2->GetTargetBounds().ToString()); + EXPECT_EQ(normal_window_bounds, window2->GetTargetBounds()); } // Tests that beginning window selection hides the app list. TEST_F(WindowSelectorTest, SelectingHidesAppList) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); @@ -1018,7 +983,7 @@ // stay invisible (A minimized window is cloned during overview), // and ignored_by_shelf state is restored upon exit. TEST_F(WindowSelectorTest, MinimizedWindowState) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); wm::WindowState* window_state = wm::GetWindowState(window1.get()); window_state->Minimize(); @@ -1040,7 +1005,7 @@ // Tests that it is safe to destroy a window while the overview header animation // is still active. See http://crbug.com/646350. TEST_F(WindowSelectorTest, SafeToDestroyWindowDuringAnimation) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); { // Quickly enter and exit overview mode to activate header animations. std::unique_ptr<aura::Window> window(CreateWindow(bounds)); @@ -1051,7 +1016,7 @@ gfx::SlideAnimation* animation = GetBackgroundViewAnimationForWindow(0, window.get()); - ASSERT_NE(nullptr, animation); + ASSERT_TRUE(animation); ToggleOverview(); EXPECT_FALSE(IsSelecting()); if (animation) @@ -1086,7 +1051,7 @@ // Tests that a newly created window aborts overview. TEST_F(WindowSelectorTest, NewWindowCancelsOveriew) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); ToggleOverview(); @@ -1099,7 +1064,7 @@ // Tests that a window activation exits overview mode. TEST_F(WindowSelectorTest, ActivationCancelsOveriew) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); window2->Focus(); @@ -1118,7 +1083,7 @@ // Tests that exiting overview mode without selecting a window restores focus // to the previously focused window. TEST_F(WindowSelectorTest, CancelRestoresFocus) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window(CreateWindow(bounds)); wm::ActivateWindow(window.get()); EXPECT_EQ(window.get(), wm::GetFocusedWindow()); @@ -1134,7 +1099,7 @@ // Tests that overview mode is exited if the last remaining window is destroyed. TEST_F(WindowSelectorTest, LastWindowDestroyed) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); ToggleOverview(); @@ -1147,7 +1112,7 @@ // Tests that entering overview mode restores a window to its original // target location. TEST_F(WindowSelectorTest, QuickReentryRestoresInitialTransform) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window(CreateWindow(bounds)); gfx::Rect initial_bounds = GetTransformedBounds(window.get()); ToggleOverview(); @@ -1169,7 +1134,7 @@ // Tests that windows with modal child windows are transformed with the modal // child even though not activatable themselves. TEST_F(WindowSelectorTest, ModalChild) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> child1(CreateWindow(bounds)); child1->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); @@ -1264,7 +1229,7 @@ // Tests shutting down during overview. TEST_F(WindowSelectorTest, Shutdown) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); // These windows will be deleted when the test exits and the Shell instance // is shut down. std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); @@ -1347,7 +1312,7 @@ window.get()); event_generator.PressLeftButton(); event_generator.MoveMouseBy(10, 10); - EXPECT_EQ(window->bounds().ToString(), "10,10 100x100"); + EXPECT_EQ(gfx::Rect(10, 10, 100, 100), window->bounds()); ToggleOverview(); ASSERT_TRUE(IsSelecting()); @@ -1360,35 +1325,32 @@ event_generator.MoveMouseBy(10, 10); event_generator.ReleaseLeftButton(); RunAllPendingInMessageLoop(); - EXPECT_EQ(window->bounds().ToString(), "30,30 100x100"); - - return; + EXPECT_EQ(gfx::Rect(30, 30, 100, 100), window->bounds()); } // Test that a label is created under the window on entering overview mode. TEST_F(WindowSelectorTest, CreateLabelUnderWindow) { std::unique_ptr<aura::Window> window(CreateWindow(gfx::Rect(0, 0, 300, 500))); - base::string16 window_title = base::UTF8ToUTF16("My window"); + const base::string16 window_title = base::UTF8ToUTF16("My window"); window->SetTitle(window_title); ToggleOverview(); WindowSelectorItem* window_item = GetWindowItemsForRoot(0).back().get(); views::Label* label = GetLabelView(window_item); - // Has the label view been created? ASSERT_TRUE(label); // Verify the label matches the window title. - EXPECT_EQ(label->text(), window_title); + EXPECT_EQ(window_title, label->text()); // Update the window title and check that the label is updated, too. - base::string16 updated_title = base::UTF8ToUTF16("Updated title"); + const base::string16 updated_title = base::UTF8ToUTF16("Updated title"); window->SetTitle(updated_title); - EXPECT_EQ(label->text(), updated_title); + EXPECT_EQ(updated_title, label->text()); // Labels are located based on target_bounds, not the actual window item // bounds. gfx::Rect label_bounds = label->GetWidget()->GetWindowBoundsInScreen(); label_bounds.Inset(kWindowMargin, kWindowMargin); - EXPECT_EQ(window_item->target_bounds(), label_bounds); + EXPECT_EQ(label_bounds, window_item->target_bounds()); } // Tests that overview updates the window positions if the display orientation @@ -1446,7 +1408,7 @@ SendKey(ui::VKEY_RIGHT); EXPECT_EQ(window1, GetSelectedWindow()); - SendCtrlKey(ui::VKEY_W); + SendKey(ui::VKEY_W, ui::EF_CONTROL_DOWN); EXPECT_TRUE(widget->IsClosed()); } @@ -2196,7 +2158,7 @@ // Tests window list animation states are correctly updated. TEST_F(WindowSelectorTest, SetWindowListAnimationStates) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); @@ -2229,7 +2191,7 @@ // Tests window list animation states are correctly updated with selected // window. TEST_F(WindowSelectorTest, SetWindowListAnimationStatesWithSelectedWindow) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); @@ -2265,7 +2227,7 @@ // Tests OverviewWindowAnimationObserver can handle deleted window. TEST_F(WindowSelectorTest, OverviewWindowAnimationObserverCanHandleDeletedWindow) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); @@ -2305,7 +2267,7 @@ // Tests can handle OverviewWindowAnimationObserver was deleted. TEST_F(WindowSelectorTest, HandleOverviewWindowAnimationObserverWasDeleted) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); @@ -2342,7 +2304,7 @@ // Tests can handle |gained_active| window is not in the |window_grid| when // OnWindowActivated. TEST_F(WindowSelectorTest, HandleActiveWindowNotInWindowGrid) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); @@ -2381,7 +2343,7 @@ // animations. // Fails consistently; see https://crbug.com/812497. TEST_F(WindowSelectorTest, DISABLED_HandleAlwaysOnTopWindow) { - gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); @@ -2606,7 +2568,6 @@ ToggleOverview(); WindowSelectorItem* item1 = GetWindowItemForWindow(0, window1.get()); WindowSelectorItem* item2 = GetWindowItemForWindow(0, window2.get()); - // Start the drag on |item1|. Verify the dragged item, |item1| has both the // close button and titlebar hidden. All other items, |item2| should only have // the close button hidden. @@ -2978,7 +2939,7 @@ // snaps the window. If two windows are snapped to left and right side of the // screen, exit the overview mode. TEST_F(SplitViewWindowSelectorTest, DragOverviewWindowToSnap) { - const gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); @@ -3110,7 +3071,7 @@ // overview mode when split view is enabled. TEST_F(SplitViewWindowSelectorTest, WindowGridSizeWhileDraggingWithSplitView) { // Add three windows and enter overview mode. - const gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); @@ -3210,7 +3171,7 @@ // mode, snapping the window to one side of the screen will end the overview // mode since there is no more window left in the overview window grid. TEST_F(SplitViewWindowSelectorTest, EmptyWindowsListExitOverview) { - const gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); ToggleOverview(); @@ -3295,7 +3256,7 @@ // Verify that the split view overview overlay has the expected state. TEST_F(SplitViewWindowSelectorTest, SplitViewOverviewOverlayState) { - const gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); @@ -3457,6 +3418,8 @@ // Test the overview window drag functionalities when screen rotates. TEST_F(SplitViewWindowSelectorTest, SplitViewRotationTest) { + using svc = SplitViewController; + UpdateDisplay("807x407"); int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); display::DisplayManager* display_manager = Shell::Get()->display_manager(); @@ -3471,7 +3434,7 @@ EXPECT_EQ(test_api.GetCurrentOrientation(), blink::kWebScreenOrientationLockLandscapePrimary); - const gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); @@ -3481,8 +3444,7 @@ WindowSelectorItem* selector_item1 = GetWindowItemForWindow(grid_index, window1.get()); DragWindowTo(selector_item1, gfx::Point(0, 0)); - EXPECT_EQ(split_view_controller()->state(), - SplitViewController::LEFT_SNAPPED); + EXPECT_EQ(split_view_controller()->state(), svc::LEFT_SNAPPED); EXPECT_EQ(split_view_controller()->left_window(), window1.get()); // Test that dragging |window2| to the right of the screen snaps it to right. @@ -3492,8 +3454,7 @@ split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window2.get()); gfx::Point end_location2(work_area_rect.width(), work_area_rect.height()); DragWindowTo(selector_item2, end_location2); - EXPECT_EQ(split_view_controller()->state(), - SplitViewController::BOTH_SNAPPED); + EXPECT_EQ(split_view_controller()->state(), svc::BOTH_SNAPPED); EXPECT_EQ(split_view_controller()->right_window(), window2.get()); // Test that |left_window_| was snapped to left after rotated 0 degree. @@ -3513,8 +3474,7 @@ // Test that dragging |window1| to the top of the screen snaps it to left. selector_item1 = GetWindowItemForWindow(grid_index, window1.get()); DragWindowTo(selector_item1, gfx::Point(0, 0)); - EXPECT_EQ(split_view_controller()->state(), - SplitViewController::LEFT_SNAPPED); + EXPECT_EQ(split_view_controller()->state(), svc::LEFT_SNAPPED); EXPECT_EQ(split_view_controller()->left_window(), window1.get()); // Test that dragging |window2| to the bottom of the screen snaps it to right. @@ -3523,8 +3483,7 @@ split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window2.get()); end_location2 = gfx::Point(work_area_rect.width(), work_area_rect.height()); DragWindowTo(selector_item2, end_location2, SelectorItemLocation::ORIGIN); - EXPECT_EQ(split_view_controller()->state(), - SplitViewController::BOTH_SNAPPED); + EXPECT_EQ(split_view_controller()->state(), svc::BOTH_SNAPPED); EXPECT_EQ(split_view_controller()->right_window(), window2.get()); // Test that |left_window_| was snapped to top after rotated 270 degree. @@ -3544,8 +3503,7 @@ // Test that dragging |window1| to the left of the screen snaps it to right. selector_item1 = GetWindowItemForWindow(grid_index, window1.get()); DragWindowTo(selector_item1, gfx::Point(0, 0)); - EXPECT_EQ(split_view_controller()->state(), - SplitViewController::RIGHT_SNAPPED); + EXPECT_EQ(split_view_controller()->state(), svc::RIGHT_SNAPPED); EXPECT_EQ(split_view_controller()->right_window(), window1.get()); // Test that dragging |window2| to the right of the screen snaps it to left. @@ -3554,8 +3512,7 @@ split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window2.get()); end_location2 = gfx::Point(work_area_rect.width(), work_area_rect.height()); DragWindowTo(selector_item2, end_location2, SelectorItemLocation::ORIGIN); - EXPECT_EQ(split_view_controller()->state(), - SplitViewController::BOTH_SNAPPED); + EXPECT_EQ(split_view_controller()->state(), svc::BOTH_SNAPPED); EXPECT_EQ(split_view_controller()->left_window(), window2.get()); // Test that |right_window_| was snapped to left after rotated 180 degree. @@ -3575,8 +3532,7 @@ // Test that dragging |window1| to the top of the screen snaps it to right. selector_item1 = GetWindowItemForWindow(grid_index, window1.get()); DragWindowTo(selector_item1, gfx::Point(0, 0)); - EXPECT_EQ(split_view_controller()->state(), - SplitViewController::RIGHT_SNAPPED); + EXPECT_EQ(split_view_controller()->state(), svc::RIGHT_SNAPPED); EXPECT_EQ(split_view_controller()->right_window(), window1.get()); // Test that dragging |window2| to the bottom of the screen snaps it to left. @@ -3585,8 +3541,7 @@ split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window2.get()); end_location2 = gfx::Point(work_area_rect.width(), work_area_rect.height()); DragWindowTo(selector_item2, end_location2); - EXPECT_EQ(split_view_controller()->state(), - SplitViewController::BOTH_SNAPPED); + EXPECT_EQ(split_view_controller()->state(), svc::BOTH_SNAPPED); EXPECT_EQ(split_view_controller()->left_window(), window2.get()); // Test that |right_window_| was snapped to top after rotated 90 degree. @@ -3603,7 +3558,7 @@ TEST_F(SplitViewWindowSelectorTest, SplitViewOverviewBothActiveTest) { UpdateDisplay("907x407"); - const gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); @@ -3753,7 +3708,7 @@ TEST_F(SplitViewWindowSelectorTest, DragDividerToExitTest) { UpdateDisplay("907x407"); - const gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); @@ -3828,7 +3783,7 @@ } TEST_F(SplitViewWindowSelectorTest, SnappedWindowBoundsTest) { - const gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); const int kMinimumBoundSize = 100; const gfx::Size size(kMinimumBoundSize, kMinimumBoundSize); @@ -3900,7 +3855,7 @@ // still active. TEST_F(SplitViewWindowSelectorTest, DividerDraggedToEdgeReturnsWindowToOverviewList) { - const gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); @@ -3947,7 +3902,7 @@ base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kAshEnableNewOverviewUi); - const gfx::Rect bounds(0, 0, 400, 400); + const gfx::Rect bounds(400, 400); std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); ToggleOverview();
diff --git a/base/sys_info.cc b/base/sys_info.cc index 645605a..379d7f26 100644 --- a/base/sys_info.cc +++ b/base/sys_info.cc
@@ -44,6 +44,15 @@ return AmountOfAvailablePhysicalMemoryImpl(); } +bool SysInfo::IsLowEndDevice() { + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableLowEndDeviceMode)) { + return true; + } + + return IsLowEndDeviceImpl(); +} + #if !defined(OS_ANDROID) bool DetectLowEndDevice() { @@ -62,7 +71,7 @@ g_lazy_low_end_device = LAZY_INSTANCE_INITIALIZER; // static -bool SysInfo::IsLowEndDevice() { +bool SysInfo::IsLowEndDeviceImpl() { return g_lazy_low_end_device.Get().value(); } #endif
diff --git a/base/sys_info.h b/base/sys_info.h index d435d58..6e58715 100644 --- a/base/sys_info.h +++ b/base/sys_info.h
@@ -172,6 +172,7 @@ static int64_t AmountOfPhysicalMemoryImpl(); static int64_t AmountOfAvailablePhysicalMemoryImpl(); + static bool IsLowEndDeviceImpl(); #if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_AIX) static int64_t AmountOfAvailablePhysicalMemory(
diff --git a/base/sys_info_android.cc b/base/sys_info_android.cc index 1d1710c7..7704796 100644 --- a/base/sys_info_android.cc +++ b/base/sys_info_android.cc
@@ -222,7 +222,7 @@ android::SysUtils::IsLowEndDeviceFromJni> >::Leaky g_lazy_low_end_device = LAZY_INSTANCE_INITIALIZER; -bool SysInfo::IsLowEndDevice() { +bool SysInfo::IsLowEndDeviceImpl() { // This code might be used in some environments // which might not have a Java environment. // Note that we need to call the Java version here.
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc index 88b57dd..520b354 100644 --- a/cc/paint/paint_op_buffer_unittest.cc +++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -19,7 +19,7 @@ #include "cc/test/test_skcanvas.h" #include "cc/test/transfer_cache_test_helper.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/effects/SkBlurMaskFilter.h" +#include "third_party/skia/include/core/SkMaskFilter.h" #include "third_party/skia/include/effects/SkColorMatrixFilter.h" #include "third_party/skia/include/effects/SkDashPathEffect.h" #include "third_party/skia/include/effects/SkLayerDrawLooper.h" @@ -1134,9 +1134,8 @@ SkScalar intervals[] = {1.f, 1.f}; flags.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); - flags.setMaskFilter( - SkBlurMaskFilter::Make(SkBlurStyle::kOuter_SkBlurStyle, 4.3f, - test_rects[0], kHigh_SkBlurQuality)); + flags.setMaskFilter(SkMaskFilter::MakeBlur( + SkBlurStyle::kOuter_SkBlurStyle, 4.3f, test_rects[0])); flags.setColorFilter(SkColorMatrixFilter::MakeLightingFilter( SK_ColorYELLOW, SK_ColorGREEN));
diff --git a/cc/paint/paint_op_perftest.cc b/cc/paint/paint_op_perftest.cc index 93d7ef0..ee9f92f 100644 --- a/cc/paint/paint_op_perftest.cc +++ b/cc/paint/paint_op_perftest.cc
@@ -11,7 +11,7 @@ #include "cc/paint/paint_op_buffer_serializer.h" #include "cc/test/transfer_cache_test_helper.h" #include "testing/perf/perf_test.h" -#include "third_party/skia/include/effects/SkBlurMaskFilter.h" +#include "third_party/skia/include/core/SkMaskFilter.h" #include "third_party/skia/include/effects/SkColorMatrixFilter.h" #include "third_party/skia/include/effects/SkDashPathEffect.h" #include "third_party/skia/include/effects/SkLayerDrawLooper.h" @@ -123,9 +123,8 @@ PaintFlags flags; SkScalar intervals[] = {1.f, 1.f}; flags.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0)); - flags.setMaskFilter(SkBlurMaskFilter::Make(SkBlurStyle::kOuter_SkBlurStyle, - 4.3f, SkRect::MakeXYWH(1, 1, 1, 1), - kHigh_SkBlurQuality)); + flags.setMaskFilter(SkMaskFilter::MakeBlur( + SkBlurStyle::kOuter_SkBlurStyle, 4.3f, SkRect::MakeXYWH(1, 1, 1, 1))); flags.setColorFilter( SkColorMatrixFilter::MakeLightingFilter(SK_ColorYELLOW, SK_ColorGREEN));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java index 08c032a..a29c4db 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -231,7 +231,13 @@ .setIcon(Icon.createWithBitmap(icon)) .setIntent(shortcutIntent) .build(); - sShortcutManager.requestPinShortcut(shortcutInfo, null); + try { + sShortcutManager.requestPinShortcut(shortcutInfo, null); + } catch (IllegalStateException e) { + Log.d(TAG, + "Could not create pinned shortcut: device is locked, or " + + "activity is backgrounded."); + } } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java index 6db1811..1b3f887 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/ClientManager.java
@@ -265,6 +265,17 @@ mUidHasCalledWarmup.put(uid, true); } + /** + * @return all the sessions originating from a given {@code uid}. + */ + public synchronized List<CustomTabsSessionToken> uidToSessions(int uid) { + List<CustomTabsSessionToken> sessions = new ArrayList<>(); + for (Map.Entry<CustomTabsSessionToken, SessionParams> entry : mSessionParams.entrySet()) { + if (entry.getValue().uid == uid) sessions.add(entry.getKey()); + } + return sessions; + } + /** Updates the client behavior stats and returns whether speculation is allowed. * * The first call to the "low priority" mode is not throttled. Subsequent ones are.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java index 5dd7d11..eaada0b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -17,6 +17,7 @@ import android.os.Bundle; import android.os.Process; import android.os.SystemClock; +import android.support.annotation.Nullable; import android.support.customtabs.CustomTabsCallback; import android.support.customtabs.CustomTabsIntent; import android.support.customtabs.CustomTabsService; @@ -94,6 +95,8 @@ static final String BOTTOM_BAR_SCROLL_STATE_CALLBACK = "onBottomBarScrollStateChanged"; @VisibleForTesting static final String OPEN_IN_BROWSER_CALLBACK = "onOpenInBrowser"; + @VisibleForTesting + static final String ON_WARMUP_COMPLETED = "onWarmupCompleted"; // For CustomTabs.SpeculationStatusOnStart, see tools/metrics/enums.xml. Append only. private static final int SPECULATION_STATUS_ON_START_ALLOWED = 0; @@ -211,7 +214,6 @@ private final AtomicBoolean mWarmupHasBeenFinished = new AtomicBoolean(); private ExternalPrerenderHandler mExternalPrerenderHandler; private boolean mForcePrerenderForTesting; - private volatile Runnable mWarmupFinishedCallback; // Conversion between native TimeTicks and SystemClock.uptimeMillis(). private long mNativeTickOffsetUs; @@ -379,7 +381,8 @@ private boolean warmupInternal(final boolean mayCreateSpareWebContents) { // Here and in mayLaunchUrl(), don't do expensive work for background applications. if (!isCallerForegroundOrSelf()) return false; - mClientManager.recordUidHasCalledWarmup(Binder.getCallingUid()); + int uid = Binder.getCallingUid(); + mClientManager.recordUidHasCalledWarmup(uid); final boolean initialized = !mWarmupHasBeenCalled.compareAndSet(false, true); // The call is non-blocking and this must execute on the UI thread, post chained tasks. @@ -396,80 +399,61 @@ // (1) if (!initialized) { - tasks.add(new Runnable() { - @Override - public void run() { - try (TraceEvent e = - TraceEvent.scoped("CustomTabsConnection.initializeBrowser()")) { - initializeBrowser(mContext); - ChromeBrowserInitializer.initNetworkChangeNotifier(mContext); - mWarmupHasBeenFinished.set(true); - } + tasks.add(() -> { + try (TraceEvent e = TraceEvent.scoped("CustomTabsConnection.initializeBrowser()")) { + initializeBrowser(mContext); + ChromeBrowserInitializer.initNetworkChangeNotifier(mContext); + mWarmupHasBeenFinished.set(true); } }); } // (2) if (mayCreateSpareWebContents && mSpeculation == null) { - tasks.add(new Runnable() { - @Override - public void run() { - // Temporary fix for https://crbug.com/797832. - // TODO(lizeb): Properly fix instead of papering over the bug, this code should - // not be scheduled unless startup is done. See https://crbug.com/797832. - if (!BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER) - .isStartupSuccessfullyCompleted()) { - return; - } - try (TraceEvent e = TraceEvent.scoped("CreateSpareWebContents")) { - WarmupManager.getInstance().createSpareWebContents(); - } + tasks.add(() -> { + // Temporary fix for https://crbug.com/797832. + // TODO(lizeb): Properly fix instead of papering over the bug, this code should + // not be scheduled unless startup is done. See https://crbug.com/797832. + if (!BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER) + .isStartupSuccessfullyCompleted()) { + return; + } + try (TraceEvent e = TraceEvent.scoped("CreateSpareWebContents")) { + WarmupManager.getInstance().createSpareWebContents(); } }); } // (3) - tasks.add(new Runnable() { - @Override - public void run() { - try (TraceEvent e = TraceEvent.scoped("InitializeViewHierarchy")) { - WarmupManager.getInstance().initializeViewHierarchy(mContext, - R.layout.custom_tabs_control_container, R.layout.custom_tabs_toolbar); - } + tasks.add(() -> { + try (TraceEvent e = TraceEvent.scoped("InitializeViewHierarchy")) { + WarmupManager.getInstance().initializeViewHierarchy(mContext, + R.layout.custom_tabs_control_container, R.layout.custom_tabs_toolbar); } }); if (!initialized) { - tasks.add(new Runnable() { - @Override - public void run() { - try (TraceEvent e = TraceEvent.scoped("WarmupInternalFinishInitialization")) { - // (4) - Profile profile = Profile.getLastUsedProfile(); - new LoadingPredictor(profile).startInitialization(); + tasks.add(() -> { + try (TraceEvent e = TraceEvent.scoped("WarmupInternalFinishInitialization")) { + // (4) + Profile profile = Profile.getLastUsedProfile(); + new LoadingPredictor(profile).startInitialization(); - // (5) - // The throttling database uses shared preferences, that can cause a - // StrictMode violation on the first access. Make sure that this access is - // not in mayLauchUrl. - RequestThrottler.loadInBackground(mContext); - } + // (5) + // The throttling database uses shared preferences, that can cause a + // StrictMode violation on the first access. Make sure that this access is + // not in mayLauchUrl. + RequestThrottler.loadInBackground(mContext); } }); } - if (mWarmupFinishedCallback != null) tasks.add(mWarmupFinishedCallback); + tasks.add(() -> notifyWarmupIsDone(uid)); tasks.start(false); mWarmupTasks = tasks; return true; } - /** Sets a callback to be notified of the completion of all the warmup() tasks. */ - @VisibleForTesting - void setWarmupCompletedCallbackForTesting(Runnable cb) { - mWarmupFinishedCallback = cb; - } - /** @return the URL or null if it's invalid. */ private boolean isValid(Uri uri) { if (uri == null) return false; @@ -692,23 +676,19 @@ if (!mClientManager.bindToPostMessageServiceForSession(session)) return false; final int uid = Binder.getCallingUid(); - ThreadUtils.postOnUiThread(new Runnable() { - @Override - public void run() { - // If the API is not enabled, we don't set the post message origin, which will - // avoid PostMessageHandler initialization and disallow postMessage calls. - if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_POST_MESSAGE_API)) return; + ThreadUtils.postOnUiThread(() -> { + // If the API is not enabled, we don't set the post message origin, which will avoid + // PostMessageHandler initialization and disallow postMessage calls. + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_POST_MESSAGE_API)) return; - // Attempt to verify origin synchronously. If successful directly initialize - // postMessage channel for session. - Uri verifiedOrigin = verifyOriginForSession(session, uid, postMessageOrigin); - if (verifiedOrigin == null) { - mClientManager.verifyAndInitializeWithPostMessageOriginForSession( - session, postMessageOrigin, CustomTabsService.RELATION_USE_AS_ORIGIN); - } else { - mClientManager.initializeWithPostMessageOriginForSession( - session, verifiedOrigin); - } + // Attempt to verify origin synchronously. If successful directly initialize postMessage + // channel for session. + Uri verifiedOrigin = verifyOriginForSession(session, uid, postMessageOrigin); + if (verifiedOrigin == null) { + mClientManager.verifyAndInitializeWithPostMessageOriginForSession( + session, postMessageOrigin, CustomTabsService.RELATION_USE_AS_ORIGIN); + } else { + mClientManager.initializeWithPostMessageOriginForSession(session, verifiedOrigin); } }); return true; @@ -1118,6 +1098,14 @@ return extras; } + private void notifyWarmupIsDone(int uid) { + ThreadUtils.assertOnUiThread(); + // Notifies all the sessions, as warmup() is tied to a UID, not a session. + for (CustomTabsSessionToken session : mClientManager.uidToSessions(uid)) { + safeExtraCallback(session, ON_WARMUP_COMPLETED, null); + } + } + /** * Notifies the application of a page load metric for a single metric. * @@ -1183,8 +1171,8 @@ * Wraps calling extraCallback in a try/catch so exceptions thrown by the host app don't crash * Chrome. See https://crbug.com/517023. */ - private boolean safeExtraCallback(CustomTabsSessionToken session, String callbackName, - Bundle args) { + private boolean safeExtraCallback( + CustomTabsSessionToken session, String callbackName, @Nullable Bundle args) { CustomTabsCallback callback = mClientManager.getCallbackForSession(session); if (callback == null) return false; @@ -1296,12 +1284,7 @@ */ @VisibleForTesting void cleanUpSession(final CustomTabsSessionToken session) { - ThreadUtils.runOnUiThread(new Runnable() { - @Override - public void run() { - mClientManager.cleanupSession(session); - } - }); + ThreadUtils.runOnUiThread(() -> mClientManager.cleanupSession(session)); } @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java index 9e57f82..8fbc4052 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
@@ -485,4 +485,9 @@ TextView getEmptyViewForTests() { return mEmptyView; } + + @VisibleForTesting + public RecyclerView getRecyclerViewForTests() { + return mRecyclerView; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java index ef6e344..6e4fdeb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
@@ -157,7 +157,7 @@ mRoot.addChild(mSiteSection); } - if (FeatureUtilities.isChromeHomeEnabled()) { + if (FeatureUtilities.isChromeDuplexEnabled()) { if (mSigninPromo != null) mRoot.addChild(mSigninPromo); mRoot.addChildren(mAllDismissed);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java index a461b5f6..7f2eab5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/OriginVerifierTest.java
@@ -10,6 +10,7 @@ import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -17,6 +18,7 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.browserservices.OriginVerifier.OriginVerificationListener; +import org.chromium.content.browser.test.NativeLibraryTestRule; import java.util.concurrent.Callable; import java.util.concurrent.Semaphore; @@ -25,6 +27,9 @@ /** Tests for OriginVerifier. */ @RunWith(BaseJUnit4ClassRunner.class) public class OriginVerifierTest { + @Rule + public NativeLibraryTestRule mNativeLibraryTestRule = new NativeLibraryTestRule(); + private static final long TIMEOUT_MS = 1000; private static final byte[] BYTE_ARRAY = new byte[] {(byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0x10, (byte) 0x20, (byte) 0x30, (byte) 0x01, (byte) 0x02}; @@ -40,9 +45,9 @@ private static final String SHA_256_FINGERPRINT = ChromeVersionInfo.isOfficialBuild() ? SHA_256_FINGERPRINT_OFFICIAL : SHA_256_FINGERPRINT_PUBLIC; - private static final Origin TEST_HTTPS_ORIGIN_1 = new Origin("https://www.example.com"); - private static final Origin TEST_HTTPS_ORIGIN_2 = new Origin("https://www.android.com"); - private static final Origin TEST_HTTP_ORIGIN = new Origin("http://www.android.com"); + + private Origin mHttpsOrigin; + private Origin mHttpOrigin; private class TestOriginVerificationListener implements OriginVerificationListener { @Override @@ -63,6 +68,11 @@ @Before public void setUp() throws Exception { + mNativeLibraryTestRule.loadNativeLibraryNoBrowserProcess(); + + mHttpsOrigin = new Origin("https://www.example.com"); + mHttpOrigin = new Origin("http://www.android.com"); + mHandleAllUrlsVerifier = new OriginVerifier(new TestOriginVerificationListener(), PACKAGE_NAME, CustomTabsService.RELATION_HANDLE_ALL_URLS); mUseAsOriginVerifier = new OriginVerifier(new TestOriginVerificationListener(), @@ -86,7 +96,7 @@ Assert.assertTrue( mVerificationResultSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); Assert.assertFalse(mLastVerified); - ThreadUtils.postOnUiThread(() -> mHandleAllUrlsVerifier.start(TEST_HTTP_ORIGIN)); + ThreadUtils.postOnUiThread(() -> mHandleAllUrlsVerifier.start(mHttpOrigin)); Assert.assertTrue( mVerificationResultSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); Assert.assertFalse(mLastVerified); @@ -98,26 +108,26 @@ ThreadUtils.postOnUiThread( () -> OriginVerifier.addVerifiedOriginForPackage(PACKAGE_NAME, - TEST_HTTPS_ORIGIN_1, CustomTabsService.RELATION_USE_AS_ORIGIN)); - ThreadUtils.postOnUiThread(() -> mUseAsOriginVerifier.start(TEST_HTTPS_ORIGIN_1)); + mHttpsOrigin, CustomTabsService.RELATION_USE_AS_ORIGIN)); + ThreadUtils.postOnUiThread(() -> mUseAsOriginVerifier.start(mHttpsOrigin)); Assert.assertTrue( mVerificationResultSemaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); Assert.assertTrue(mLastVerified); Assert.assertTrue(ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() { @Override public Boolean call() throws Exception { - return OriginVerifier.isValidOrigin(PACKAGE_NAME, TEST_HTTPS_ORIGIN_1, + return OriginVerifier.isValidOrigin(PACKAGE_NAME, mHttpsOrigin, CustomTabsService.RELATION_USE_AS_ORIGIN); } })); Assert.assertFalse(ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() { @Override public Boolean call() throws Exception { - return OriginVerifier.isValidOrigin(PACKAGE_NAME, TEST_HTTPS_ORIGIN_1, + return OriginVerifier.isValidOrigin(PACKAGE_NAME, mHttpsOrigin, CustomTabsService.RELATION_HANDLE_ALL_URLS); } })); Assert.assertEquals(mLastPackageName, PACKAGE_NAME); - Assert.assertEquals(mLastOrigin, TEST_HTTPS_ORIGIN_1); + Assert.assertEquals(mLastOrigin, mHttpsOrigin); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index 323d0cb..f4456c0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -35,10 +35,8 @@ import android.os.SystemClock; import android.support.annotation.DrawableRes; import android.support.customtabs.CustomTabsCallback; -import android.support.customtabs.CustomTabsClient; import android.support.customtabs.CustomTabsIntent; import android.support.customtabs.CustomTabsService; -import android.support.customtabs.CustomTabsServiceConnection; import android.support.customtabs.CustomTabsSession; import android.support.customtabs.CustomTabsSessionToken; import android.support.test.InstrumentationRegistry; @@ -709,10 +707,10 @@ @Test @SmallTest @RetryOnFailure - public void testOpenInBrowser() throws InterruptedException, TimeoutException { + public void testOpenInBrowser() throws Exception { // Augment the CustomTabsSession to catch the callback. CallbackHelper callbackTriggered = new CallbackHelper(); - CustomTabsSession session = bindWithCallback(new CustomTabsCallback() { + CustomTabsSession session = CustomTabsTestUtils.bindWithCallback(new CustomTabsCallback() { @Override public void extraCallback(String callbackName, Bundle args) { if (callbackName.equals(CustomTabsConnection.OPEN_IN_BROWSER_CALLBACK)) { @@ -1031,7 +1029,7 @@ @Test @SmallTest @Feature({"UiCatalogue"}) - public void testRemoteViews() throws InterruptedException { + public void testRemoteViews() throws Exception { Intent intent = createMinimalCustomTabIntent(); Bitmap expectedIcon = createVectorDrawableBitmap(R.drawable.ic_credit_card_black, 77, 48); @@ -1058,7 +1056,7 @@ @Test @SmallTest @RetryOnFailure - public void testLaunchWithSession() throws InterruptedException, TimeoutException { + public void testLaunchWithSession() throws Exception { CustomTabsSessionToken session = warmUpAndLaunchUrlWithSession(); Assert.assertEquals(getActivity().getIntentDataProvider().getSession(), session); } @@ -1066,7 +1064,7 @@ @Test @SmallTest @RetryOnFailure - public void testLoadNewUrlWithSession() throws InterruptedException, TimeoutException { + public void testLoadNewUrlWithSession() throws Exception { final Context context = InstrumentationRegistry.getTargetContext(); final Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage); CustomTabsSessionToken session = CustomTabsSessionToken.getSessionTokenFromIntent(intent); @@ -1100,7 +1098,7 @@ @Test @SmallTest @RetryOnFailure - public void testCreateNewTab() throws InterruptedException, TimeoutException { + public void testCreateNewTab() throws Exception { final String testUrl = mTestServer.getURL( "/chrome/test/data/android/customtabs/test_window_open.html"); mCustomTabActivityTestRule.startCustomTabActivityWithIntent( @@ -1130,7 +1128,7 @@ @Test @SmallTest @RetryOnFailure - public void testReferrerAddedAutomatically() throws InterruptedException, TimeoutException { + public void testReferrerAddedAutomatically() throws Exception { final Context context = InstrumentationRegistry.getInstrumentation() .getTargetContext() .getApplicationContext(); @@ -1165,7 +1163,7 @@ @Test @SmallTest @RetryOnFailure - public void testVerifiedReferrer() throws InterruptedException, TimeoutException { + public void testVerifiedReferrer() throws Exception { final Context context = InstrumentationRegistry.getInstrumentation() .getTargetContext() .getApplicationContext(); @@ -1207,10 +1205,10 @@ */ @Test @SmallTest - public void testCallbacksAreSent() throws InterruptedException { + public void testCallbacksAreSent() throws Exception { final Semaphore navigationStartSemaphore = new Semaphore(0); final Semaphore navigationFinishedSemaphore = new Semaphore(0); - CustomTabsSession session = bindWithCallback(new CustomTabsCallback() { + CustomTabsSession session = CustomTabsTestUtils.bindWithCallback(new CustomTabsCallback() { @Override public void onNavigationEvent(int navigationEvent, Bundle extras) { Assert.assertNotEquals(CustomTabsCallback.NAVIGATION_FAILED, navigationEvent); @@ -1241,7 +1239,7 @@ @Test @SmallTest @RetryOnFailure - public void testPageLoadMetricIsSent() throws InterruptedException { + public void testPageLoadMetricIsSent() throws Exception { final AtomicReference<Long> firstContentfulPaintMs = new AtomicReference<>(-1L); final AtomicReference<Long> activityStartTimeMs = new AtomicReference<>(-1L); final AtomicReference<Long> loadEventStartMs = new AtomicReference<>(-1L); @@ -1280,7 +1278,7 @@ } }; - CustomTabsSession session = bindWithCallback(cb); + CustomTabsSession session = CustomTabsTestUtils.bindWithCallback(cb); Intent intent = new CustomTabsIntent.Builder(session).build().intent; intent.setData(Uri.parse(mTestPage)); intent.setComponent(new ComponentName( @@ -1322,14 +1320,14 @@ */ @Test @SmallTest - public void testNavigationHistogramsRecorded() throws InterruptedException { + public void testNavigationHistogramsRecorded() throws Exception { String startHistogramPrefix = "CustomTabs.IntentToFirstNavigationStartTime"; String commitHistogramPrefix = "CustomTabs.IntentToFirstCommitNavigationTime3"; assertSuffixedHistogramTotalCount(0, startHistogramPrefix); assertSuffixedHistogramTotalCount(0, commitHistogramPrefix); final Semaphore semaphore = new Semaphore(0); - CustomTabsSession session = bindWithCallback(new CustomTabsCallback() { + CustomTabsSession session = CustomTabsTestUtils.bindWithCallback(new CustomTabsCallback() { @Override public void onNavigationEvent(int navigationEvent, Bundle extras) { if (navigationEvent == CustomTabsCallback.NAVIGATION_FINISHED) semaphore.release(); @@ -1376,15 +1374,14 @@ */ @Test @SmallTest - public void testToolbarTitleOnlyStateWithDelayedTitle() - throws TimeoutException, InterruptedException { + public void testToolbarTitleOnlyStateWithDelayedTitle() throws Exception { final String url = mWebServer.setResponse("/test.html", DELAYED_TITLE_CHANGE, null); hideDomainAndEnsureTitleIsSet( url, CustomTabsConnection.SpeculationParams.NO_SPECULATION, "nytimes.com"); } - private void hideDomainAndEnsureTitleIsSet(final String url, int speculation, - final String expectedTitle) throws InterruptedException, TimeoutException { + private void hideDomainAndEnsureTitleIsSet( + final String url, int speculation, final String expectedTitle) throws Exception { final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait(); Context context = InstrumentationRegistry.getTargetContext(); Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, url); @@ -1428,7 +1425,7 @@ @Test @SmallTest @RetryOnFailure - public void testPostMessageBasic() throws InterruptedException, TimeoutException { + public void testPostMessageBasic() throws Exception { final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait(); Context context = InstrumentationRegistry.getTargetContext(); Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage); @@ -1468,8 +1465,7 @@ @Test @SmallTest @RetryOnFailure - public void testPostMessageWebContentsDestroyed() - throws InterruptedException, TimeoutException { + public void testPostMessageWebContentsDestroyed() throws Exception { final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait(); Context context = InstrumentationRegistry.getTargetContext(); Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage); @@ -1514,7 +1510,7 @@ @Test @SmallTest @RetryOnFailure - public void testPostMessageRequiresValidation() throws InterruptedException, TimeoutException { + public void testPostMessageRequiresValidation() throws Exception { final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait(); Context context = InstrumentationRegistry.getTargetContext(); Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage); @@ -1539,7 +1535,7 @@ @Test @SmallTest @RetryOnFailure - public void testPostMessageReceivedInPage() throws InterruptedException, TimeoutException { + public void testPostMessageReceivedInPage() throws Exception { final String url = mWebServer.setResponse("/test.html", TITLE_FROM_POSTMESSAGE_TO_CHANNEL, null); final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait(); @@ -1574,22 +1570,23 @@ @Test @SmallTest @RetryOnFailure - public void testPostMessageReceivedFromPage() throws InterruptedException, TimeoutException { + public void testPostMessageReceivedFromPage() throws Exception { final CallbackHelper messageChannelHelper = new CallbackHelper(); final CallbackHelper onPostMessageHelper = new CallbackHelper(); final String url = mWebServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null); CustomTabsTestUtils.warmUpAndWait(); - final CustomTabsSession session = bindWithCallback(new CustomTabsCallback() { - @Override - public void onMessageChannelReady(Bundle extras) { - messageChannelHelper.notifyCalled(); - } + final CustomTabsSession session = + CustomTabsTestUtils.bindWithCallback(new CustomTabsCallback() { + @Override + public void onMessageChannelReady(Bundle extras) { + messageChannelHelper.notifyCalled(); + } - @Override - public void onPostMessage(String message, Bundle extras) { - onPostMessageHelper.notifyCalled(); - } - }); + @Override + public void onPostMessage(String message, Bundle extras) { + onPostMessageHelper.notifyCalled(); + } + }); session.requestPostMessageChannel(null); Intent intent = new CustomTabsIntent.Builder(session).build().intent; intent.setData(Uri.parse(url)); @@ -1612,23 +1609,23 @@ @Test @SmallTest @RetryOnFailure - public void testPostMessageReceivedFromPageWithLateRequest() - throws InterruptedException, TimeoutException { + public void testPostMessageReceivedFromPageWithLateRequest() throws Exception { final CallbackHelper messageChannelHelper = new CallbackHelper(); final CallbackHelper onPostMessageHelper = new CallbackHelper(); final String url = mWebServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null); CustomTabsTestUtils.warmUpAndWait(); - final CustomTabsSession session = bindWithCallback(new CustomTabsCallback() { - @Override - public void onMessageChannelReady(Bundle extras) { - messageChannelHelper.notifyCalled(); - } + final CustomTabsSession session = + CustomTabsTestUtils.bindWithCallback(new CustomTabsCallback() { + @Override + public void onMessageChannelReady(Bundle extras) { + messageChannelHelper.notifyCalled(); + } - @Override - public void onPostMessage(String message, Bundle extras) { - onPostMessageHelper.notifyCalled(); - } - }); + @Override + public void onPostMessage(String message, Bundle extras) { + onPostMessageHelper.notifyCalled(); + } + }); Intent intent = new CustomTabsIntent.Builder(session).build().intent; intent.setData(Uri.parse(url)); @@ -1665,8 +1662,7 @@ @SmallTest @RetryOnFailure @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) - public void testPostMessageThroughPrerenderWithRequestBeforeMayLaunchUrl() - throws InterruptedException, TimeoutException { + public void testPostMessageThroughPrerenderWithRequestBeforeMayLaunchUrl() throws Exception { sendPostMessageDuringPrerenderTransition(BEFORE_MAY_LAUNCH_URL); } @@ -1678,8 +1674,7 @@ @SmallTest @RetryOnFailure @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) - public void testPostMessageThroughPrerenderWithRequestBeforeIntent() - throws InterruptedException, TimeoutException { + public void testPostMessageThroughPrerenderWithRequestBeforeIntent() throws Exception { sendPostMessageDuringPrerenderTransition(BEFORE_INTENT); } @@ -1691,13 +1686,11 @@ @SmallTest @RetryOnFailure @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) - public void testPostMessageThroughPrerenderWithRequestAfterIntent() - throws InterruptedException, TimeoutException { + public void testPostMessageThroughPrerenderWithRequestAfterIntent() throws Exception { sendPostMessageDuringPrerenderTransition(AFTER_INTENT); } - private void sendPostMessageDuringPrerenderTransition(int requestTime) - throws InterruptedException, TimeoutException { + private void sendPostMessageDuringPrerenderTransition(int requestTime) throws Exception { sendPostMessageDuringSpeculationTransition( requestTime, CustomTabsConnection.SpeculationParams.PRERENDER); } @@ -1711,8 +1704,7 @@ @RetryOnFailure @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @CommandLineFlags.Add("enable-features=" + ChromeFeatureList.CCT_BACKGROUND_TAB) - public void testPostMessageThroughHiddenTabWithRequestBeforeMayLaunchUrl() - throws InterruptedException, TimeoutException { + public void testPostMessageThroughHiddenTabWithRequestBeforeMayLaunchUrl() throws Exception { sendPostMessageDuringHiddenTabTransition(BEFORE_MAY_LAUNCH_URL); } @@ -1725,8 +1717,7 @@ @RetryOnFailure @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @CommandLineFlags.Add("enable-features=" + ChromeFeatureList.CCT_BACKGROUND_TAB) - public void testPostMessageThroughHiddenTabWithRequestBeforeIntent() - throws InterruptedException, TimeoutException { + public void testPostMessageThroughHiddenTabWithRequestBeforeIntent() throws Exception { sendPostMessageDuringHiddenTabTransition(BEFORE_INTENT); } @@ -1739,31 +1730,30 @@ @RetryOnFailure @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @CommandLineFlags.Add("enable-features=" + ChromeFeatureList.CCT_BACKGROUND_TAB) - public void testPostMessageThroughHiddenTabWithRequestAfterIntent() - throws InterruptedException, TimeoutException { + public void testPostMessageThroughHiddenTabWithRequestAfterIntent() throws Exception { sendPostMessageDuringHiddenTabTransition(AFTER_INTENT); } @CommandLineFlags.Add("enable-features=" + ChromeFeatureList.CCT_BACKGROUND_TAB) - private void sendPostMessageDuringHiddenTabTransition(int requestTime) - throws InterruptedException, TimeoutException { + private void sendPostMessageDuringHiddenTabTransition(int requestTime) throws Exception { sendPostMessageDuringSpeculationTransition( requestTime, CustomTabsConnection.SpeculationParams.HIDDEN_TAB); } private void sendPostMessageDuringSpeculationTransition(int requestTime, int speculationMode) - throws InterruptedException, TimeoutException { + throws Exception { final CallbackHelper messageChannelHelper = new CallbackHelper(); final String url = mWebServer.setResponse("/test.html", TITLE_FROM_POSTMESSAGE_TO_CHANNEL, null); final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait(); - final CustomTabsSession session = bindWithCallback(new CustomTabsCallback() { - @Override - public void onMessageChannelReady(Bundle extras) { - messageChannelHelper.notifyCalled(); - } - }); + final CustomTabsSession session = + CustomTabsTestUtils.bindWithCallback(new CustomTabsCallback() { + @Override + public void onMessageChannelReady(Bundle extras) { + messageChannelHelper.notifyCalled(); + } + }); Intent intent = new CustomTabsIntent.Builder(session).build().intent; intent.setData(Uri.parse(url)); @@ -1914,7 +1904,7 @@ @DisabledTest @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE) - public void testWarmupAndLaunchRegularChrome() throws InterruptedException, TimeoutException { + public void testWarmupAndLaunchRegularChrome() throws Exception { CustomTabsTestUtils.warmUpAndWait(); Intent intent = new Intent( InstrumentationRegistry.getTargetContext(), ChromeLauncherActivity.class); @@ -1942,8 +1932,7 @@ @SmallTest @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE) - public void testWarmupAndLaunchRightToolbarLayout() - throws InterruptedException, TimeoutException { + public void testWarmupAndLaunchRightToolbarLayout() throws Exception { CustomTabsTestUtils.warmUpAndWait(); mCustomTabActivityTestRule.startActivityCompletely(createMinimalCustomTabIntent()); Assert.assertNull("Should not have a tab switcher button.", @@ -2683,7 +2672,7 @@ } private void verifyHistoryAfterSpeculation(int speculationMode, boolean speculationWasAHit) - throws InterruptedException, TimeoutException { + throws Exception { String speculationUrl = mTestPage; String navigationUrl = speculationWasAHit ? mTestPage : mTestPage2; final CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait(); @@ -2778,7 +2767,7 @@ } private CustomTabsSessionToken warmUpAndLaunchUrlWithSession(Intent intentWithSession) - throws InterruptedException, TimeoutException { + throws Exception { CustomTabsConnection connection = CustomTabsTestUtils.warmUpAndWait(); CustomTabsSessionToken token = CustomTabsSessionToken.getSessionTokenFromIntent(intentWithSession); @@ -2788,8 +2777,7 @@ return token; } - private CustomTabsSessionToken warmUpAndLaunchUrlWithSession() - throws InterruptedException, TimeoutException { + private CustomTabsSessionToken warmUpAndLaunchUrlWithSession() throws Exception { return warmUpAndLaunchUrlWithSession(CustomTabsTestUtils.createMinimalCustomTabIntent( InstrumentationRegistry.getTargetContext(), mTestPage)); } @@ -2819,29 +2807,6 @@ } } - private CustomTabsSession bindWithCallback(final CustomTabsCallback callback) { - final AtomicReference<CustomTabsSession> sessionReference = new AtomicReference<>(null); - CustomTabsClient.bindCustomTabsService(InstrumentationRegistry.getContext(), - InstrumentationRegistry.getTargetContext().getPackageName(), - new CustomTabsServiceConnection() { - @Override - public void onServiceDisconnected(ComponentName name) {} - - @Override - public void onCustomTabsServiceConnected( - ComponentName name, CustomTabsClient client) { - sessionReference.set(client.newSession(callback)); - } - }); - CriteriaHelper.pollInstrumentationThread(new Criteria() { - @Override - public boolean isSatisfied() { - return sessionReference.get() != null; - } - }); - return sessionReference.get(); - } - /** * A helper class to monitor sending status of a {@link PendingIntent}. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java index 95a3479..f542c595 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
@@ -6,13 +6,19 @@ import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE; +import android.content.ComponentName; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Process; +import android.support.customtabs.CustomTabsCallback; +import android.support.customtabs.CustomTabsClient; import android.support.customtabs.CustomTabsService; +import android.support.customtabs.CustomTabsServiceConnection; +import android.support.customtabs.CustomTabsSession; import android.support.customtabs.CustomTabsSessionToken; +import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import org.junit.After; @@ -26,6 +32,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryProcessType; +import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.RetryOnFailure; @@ -45,7 +52,6 @@ import java.util.concurrent.FutureTask; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; /** Tests for CustomTabsConnection. */ @@ -106,7 +112,7 @@ */ @Test @SmallTest - public void testCanWarmup() throws InterruptedException, TimeoutException { + public void testCanWarmup() throws Exception { CustomTabsTestUtils.warmUpAndWait(); CustomTabsTestUtils.warmUpAndWait(); } @@ -114,7 +120,7 @@ @Test @SmallTest @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) - public void testCreateSpareRenderer() throws InterruptedException, TimeoutException { + public void testCreateSpareRenderer() throws Exception { CustomTabsTestUtils.warmUpAndWait(); // On UI thread because: // 1. takeSpareWebContents needs to be called from the UI thread. @@ -135,8 +141,7 @@ @Test @SmallTest @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) - public void testCreateSpareRendererCanBeRecreated() - throws InterruptedException, TimeoutException { + public void testCreateSpareRendererCanBeRecreated() throws Exception { CustomTabsTestUtils.warmUpAndWait(); ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override @@ -157,7 +162,7 @@ @Test @SmallTest @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) - public void testPrerenderDestroysSpareRenderer() throws InterruptedException, TimeoutException { + public void testPrerenderDestroysSpareRenderer() throws Exception { CustomTabsConnection.getInstance().setForcePrerender(true); final CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true); ThreadUtils.runOnUiThreadBlocking(new Runnable() { @@ -181,8 +186,7 @@ @Test @SmallTest @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) - public void testPrerenderAndDisconnectOnOtherThread() - throws InterruptedException, TimeoutException { + public void testPrerenderAndDisconnectOnOtherThread() throws Exception { final CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true); final Thread otherThread = new Thread(new Runnable() { @Override @@ -203,8 +207,7 @@ @Test @SmallTest @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) - public void testMayLaunchUrlKeepsSpareRendererWithoutPrerendering() - throws InterruptedException, TimeoutException { + public void testMayLaunchUrlKeepsSpareRendererWithoutPrerendering() throws Exception { CustomTabsTestUtils.warmUpAndWait(); final CustomTabsSessionToken token = CustomTabsSessionToken.createMockSessionTokenForTesting(); @@ -225,7 +228,7 @@ @Test @SmallTest - public void testMayLaunchUrlNullOrEmptyUrl() throws InterruptedException, TimeoutException { + public void testMayLaunchUrlNullOrEmptyUrl() throws Exception { assertWarmupAndMayLaunchUrl(null, null, true); CustomTabsTestUtils.cleanupSessions(mCustomTabsConnection); // Resets throttling. assertWarmupAndMayLaunchUrl(null, "", true); @@ -315,8 +318,7 @@ @Test @SmallTest - public void testLowConfidenceMayLaunchUrlOnlyAcceptUris() - throws InterruptedException, TimeoutException { + public void testLowConfidenceMayLaunchUrlOnlyAcceptUris() throws Exception { final CustomTabsSessionToken token = CustomTabsSessionToken.createMockSessionTokenForTesting(); Assert.assertTrue(mCustomTabsConnection.newSession(token)); @@ -343,8 +345,7 @@ @Test @SmallTest - public void testLowConfidenceMayLaunchUrlDoesntCrash() - throws InterruptedException, TimeoutException { + public void testLowConfidenceMayLaunchUrlDoesntCrash() throws Exception { final CustomTabsSessionToken token = CustomTabsSessionToken.createMockSessionTokenForTesting(); Assert.assertTrue(mCustomTabsConnection.newSession(token)); @@ -391,8 +392,7 @@ @Test @SmallTest @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) - public void testPrefetchOnlyNoPrerenderHasSpareWebContents() - throws InterruptedException, TimeoutException { + public void testPrefetchOnlyNoPrerenderHasSpareWebContents() throws Exception { CustomTabsTestUtils.warmUpAndWait(); final CustomTabsSessionToken token = CustomTabsSessionToken.createMockSessionTokenForTesting(); @@ -414,7 +414,7 @@ @SmallTest @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) @RetryOnFailure - public void testCanCancelPrerender() throws InterruptedException, TimeoutException { + public void testCanCancelPrerender() throws Exception { CustomTabsConnection.getInstance().setForcePrerender(true); final CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true); ThreadUtils.runOnUiThreadBlocking(new Runnable() { @@ -448,8 +448,8 @@ * Calls warmup() and mayLaunchUrl(), checks for the expected result * (success or failure) and returns the result code. */ - private CustomTabsSessionToken assertWarmupAndMayLaunchUrl(CustomTabsSessionToken token, - String url, boolean shouldSucceed) throws InterruptedException, TimeoutException { + private CustomTabsSessionToken assertWarmupAndMayLaunchUrl( + CustomTabsSessionToken token, String url, boolean shouldSucceed) throws Exception { CustomTabsTestUtils.warmUpAndWait(); if (token == null) { token = CustomTabsSessionToken.createMockSessionTokenForTesting(); @@ -469,8 +469,7 @@ */ @Test @SmallTest - public void testNoMayLaunchUrlWithInvalidSessionId() - throws InterruptedException, TimeoutException { + public void testNoMayLaunchUrlWithInvalidSessionId() throws Exception { assertWarmupAndMayLaunchUrl( CustomTabsSessionToken.createMockSessionTokenForTesting(), URL, false); } @@ -482,8 +481,7 @@ */ @Test @SmallTest - public void testNoMayLaunchUrlWithInvalidScheme() - throws InterruptedException, TimeoutException { + public void testNoMayLaunchUrlWithInvalidScheme() throws Exception { assertWarmupAndMayLaunchUrl(null, INVALID_SCHEME_URL, false); } @@ -494,7 +492,7 @@ */ @Test @SmallTest - public void testMayLaunchUrl() throws InterruptedException, TimeoutException { + public void testMayLaunchUrl() throws Exception { assertWarmupAndMayLaunchUrl(null, URL, true); } @@ -505,7 +503,7 @@ */ @Test @SmallTest - public void testMultipleMayLaunchUrl() throws InterruptedException, TimeoutException { + public void testMultipleMayLaunchUrl() throws Exception { CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true); mCustomTabsConnection.resetThrottling(Process.myUid()); assertWarmupAndMayLaunchUrl(token, URL, true); @@ -518,7 +516,7 @@ */ @Test @SmallTest - public void testForgetsSession() throws InterruptedException, TimeoutException { + public void testForgetsSession() throws Exception { CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true); CustomTabsTestUtils.cleanupSessions(mCustomTabsConnection); assertWarmupAndMayLaunchUrl(token, URL, false); @@ -561,7 +559,7 @@ */ @Test @SmallTest - public void testThrottleMayLaunchUrl() throws InterruptedException, TimeoutException { + public void testThrottleMayLaunchUrl() throws Exception { CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true); int successfulRequests = 0; // Send a burst of requests instead of checking for precise delays to avoid flakiness. @@ -577,7 +575,7 @@ */ @Test @SmallTest - public void testThrottlingIsReset() throws InterruptedException, TimeoutException { + public void testThrottlingIsReset() throws Exception { CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true); // Depending on the timing, the delay should be 100 or 200ms here. assertWarmupAndMayLaunchUrl(token, URL, true); @@ -606,7 +604,7 @@ */ @Test @SmallTest - public void testThrottlingAcrossSessions() throws InterruptedException, TimeoutException { + public void testThrottlingAcrossSessions() throws Exception { CustomTabsSessionToken token = assertWarmupAndMayLaunchUrl(null, URL, true); mCustomTabsConnection.resetThrottling(Process.myUid()); CustomTabsSessionToken token2 = assertWarmupAndMayLaunchUrl(null, URL, true); @@ -748,4 +746,49 @@ } }); } + + @Test + @SmallTest + public void testWarmupNotificationIsSent() throws Exception { + final AtomicReference<CustomTabsClient> clientReference = new AtomicReference<>(null); + final CallbackHelper waitForConnection = new CallbackHelper(); + CustomTabsClient.bindCustomTabsService(InstrumentationRegistry.getContext(), + InstrumentationRegistry.getTargetContext().getPackageName(), + new CustomTabsServiceConnection() { + @Override + public void onServiceDisconnected(ComponentName name) {} + + @Override + public void onCustomTabsServiceConnected( + ComponentName name, CustomTabsClient client) { + clientReference.set(client); + waitForConnection.notifyCalled(); + } + }); + waitForConnection.waitForCallback(0); + CustomTabsClient client = clientReference.get(); + final CallbackHelper warmupWaiter = new CallbackHelper(); + CustomTabsSession session = newSessionWithWarmupWaiter(client, warmupWaiter); + CustomTabsSession session2 = newSessionWithWarmupWaiter(client, warmupWaiter); + + // Both sessions should be notified. + Assert.assertTrue(mCustomTabsConnection.warmup(0)); + warmupWaiter.waitForCallback(0, 2); + + // Notifications should be sent even if warmup() has already been called. + Assert.assertTrue(mCustomTabsConnection.warmup(0)); + warmupWaiter.waitForCallback(2, 2); + } + + private static CustomTabsSession newSessionWithWarmupWaiter( + CustomTabsClient client, final CallbackHelper waiter) { + return client.newSession(new CustomTabsCallback() { + @Override + public void extraCallback(String callbackName, Bundle args) { + if (callbackName.equals(CustomTabsConnection.ON_WARMUP_COMPLETED)) { + waiter.notifyCalled(); + } + } + }); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java index a42c5b81..9269ae5e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsTestUtils.java
@@ -8,9 +8,14 @@ import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Bundle; import android.os.Process; +import android.support.customtabs.CustomTabsCallback; +import android.support.customtabs.CustomTabsClient; import android.support.customtabs.CustomTabsIntent; +import android.support.customtabs.CustomTabsServiceConnection; import android.support.customtabs.CustomTabsSession; +import android.support.test.InstrumentationRegistry; import org.junit.Assert; @@ -19,6 +24,7 @@ import org.chromium.chrome.browser.document.ChromeLauncherActivity; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; /** * Utility class that contains convenience calls related with custom tabs testing. @@ -49,31 +55,45 @@ } public static void cleanupSessions(final CustomTabsConnection connection) { - ThreadUtils.runOnUiThreadBlocking(new Runnable() { - @Override - public void run() { - connection.cleanupAll(); - } - }); + ThreadUtils.runOnUiThreadBlocking(connection::cleanupAll); + } + + public static CustomTabsSession bindWithCallback(final CustomTabsCallback callback) + throws InterruptedException, TimeoutException { + final AtomicReference<CustomTabsSession> sessionReference = new AtomicReference<>(null); + final CallbackHelper waitForConnection = new CallbackHelper(); + CustomTabsClient.bindCustomTabsService(InstrumentationRegistry.getContext(), + InstrumentationRegistry.getTargetContext().getPackageName(), + new CustomTabsServiceConnection() { + @Override + public void onServiceDisconnected(ComponentName name) {} + + @Override + public void onCustomTabsServiceConnected( + ComponentName name, CustomTabsClient client) { + sessionReference.set(client.newSession(callback)); + waitForConnection.notifyCalled(); + } + }); + waitForConnection.waitForCallback(0); + return sessionReference.get(); } /** Calls warmup() and waits for all the tasks to complete. Fails the test otherwise. */ public static CustomTabsConnection warmUpAndWait() throws InterruptedException, TimeoutException { CustomTabsConnection connection = setUpConnection(); - try { - final CallbackHelper startupCallbackHelper = new CallbackHelper(); - connection.setWarmupCompletedCallbackForTesting(new Runnable() { - @Override - public void run() { + final CallbackHelper startupCallbackHelper = new CallbackHelper(); + CustomTabsSession session = bindWithCallback(new CustomTabsCallback() { + @Override + public void extraCallback(String callbackName, Bundle args) { + if (callbackName.equals(CustomTabsConnection.ON_WARMUP_COMPLETED)) { startupCallbackHelper.notifyCalled(); } - }); - Assert.assertTrue(connection.warmup(0)); - startupCallbackHelper.waitForCallback(0); - } finally { - connection.setWarmupCompletedCallbackForTesting(null); - } + } + }); + Assert.assertTrue(connection.warmup(0)); + startupCallbackHelper.waitForCallback(0); return connection; } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java index 10b4b20..25f05b9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/EmulatedVrController.java
@@ -119,6 +119,9 @@ float startX, startY, endX, endY; // We need to perform the scroll over a shorter area of the touchpad in order for flinging // to work properly. + // There's technically nothing that prevents fling scrolling if fling is set to false, but + // we have yet to find any combination of steps and speed that results in a fling with the + // larger scroll area that setting fling to false uses. // TODO(https://crbug.com/820281): Figure out why this is the case - not fling scrolling // because we're using more of the touchpad doesn't make sense. float offset = fling ? 0.5f : 0.1f; @@ -144,11 +147,6 @@ Assert.fail("Unknown scroll direction enum given"); } performLinearTouchpadMovement(startX, startY, endX, endY, steps, speed); - // There's technically nothing that prevents fling scrolling if fling is set to false, but - // we have yet to find any combination of steps and speed that results in a fling with the - // larger scroll area that setting fling to false uses. As an added precaution, assume that - // a fling occurred and cancel it immediately if we're not supposed to be flinging. - if (!fling) cancelFlingScroll(); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java index 0f993ab..0c2080ee 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr_shell/VrShellControllerInputTest.java
@@ -13,6 +13,7 @@ import android.os.SystemClock; import android.support.test.filters.MediumTest; +import android.support.v7.widget.RecyclerView; import org.junit.Assert; import org.junit.Before; @@ -24,6 +25,7 @@ import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.history.HistoryPage; import org.chromium.chrome.browser.vr_shell.rules.ChromeTabbedActivityVrTestRule; import org.chromium.chrome.browser.vr_shell.util.VrTransitionUtils; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; @@ -214,6 +216,56 @@ VrTestFramework.getHtmlTestFile("test_navigation_2d_page")); } + /* + * Verifies that swiping up/down on the Daydream controller's touchpad + * scrolls a native page while in the VR browser. + */ + @Test + @MediumTest + public void testControllerScrollingNative() throws InterruptedException { + VrTransitionUtils.forceEnterVr(); + VrTransitionUtils.waitForVrEntry(POLL_TIMEOUT_LONG_MS); + // Fill history with enough items to scroll + mVrTestRule.loadUrl( + VrTestFramework.getHtmlTestFile("test_navigation_2d_page"), PAGE_LOAD_TIMEOUT_S); + mVrTestRule.loadUrl( + VrTestFramework.getHtmlTestFile("test_controller_scrolling"), PAGE_LOAD_TIMEOUT_S); + mVrTestRule.loadUrl( + VrTestFramework.getHtmlTestFile("generic_webvr_page"), PAGE_LOAD_TIMEOUT_S); + mVrTestRule.loadUrl( + VrTestFramework.getHtmlTestFile("test_navigation_webvr_page"), PAGE_LOAD_TIMEOUT_S); + mVrTestRule.loadUrl( + VrTestFramework.getHtmlTestFile("test_webvr_autopresent"), PAGE_LOAD_TIMEOUT_S); + mVrTestRule.loadUrl( + VrTestFramework.getHtmlTestFile("generic_webxr_page"), PAGE_LOAD_TIMEOUT_S); + mVrTestRule.loadUrl( + VrTestFramework.getHtmlTestFile("test_gamepad_button"), PAGE_LOAD_TIMEOUT_S); + + mVrTestRule.loadUrl("chrome://history", PAGE_LOAD_TIMEOUT_S); + + RecyclerView recyclerView = + ((HistoryPage) (mVrTestRule.getActivity().getActivityTab().getNativePage())) + .getHistoryManagerForTesting() + .getRecyclerViewForTests(); + + // Test that scrolling down works + int startScrollPoint = recyclerView.computeVerticalScrollOffset(); + // Arbitrary, but valid values to scroll smoothly + int scrollSteps = 20; + int scrollSpeed = 60; + mController.scroll(EmulatedVrController.ScrollDirection.DOWN, scrollSteps, scrollSpeed, + /* fling */ false); + int endScrollPoint = recyclerView.computeVerticalScrollOffset(); + Assert.assertTrue("Controller was able to scroll down", startScrollPoint < endScrollPoint); + + // Test that scrolling up works + startScrollPoint = endScrollPoint; + mController.scroll(EmulatedVrController.ScrollDirection.UP, scrollSteps, scrollSpeed, + /* fling */ false); + endScrollPoint = recyclerView.computeVerticalScrollOffset(); + Assert.assertTrue("Controller was able to scroll up", startScrollPoint > endScrollPoint); + } + /** * Verifies that pressing the Daydream controller's 'app' button causes the user to exit * fullscreen
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java index 3ea64842c..6e403292 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java
@@ -17,6 +17,7 @@ import android.util.Base64; import org.junit.Assert; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,6 +68,11 @@ @Rule public final NativeLibraryTestRule mNativeLibraryTestRule = new NativeLibraryTestRule(); + @Before + public void setUp() { + mNativeLibraryTestRule.loadNativeLibraryNoBrowserProcess(); + } + /** * Test that navigating a webapp whose launch intent does not specify a theme colour outside of * the webapp scope by tapping a regular link:
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java index c9b270d..ec69ef5 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
@@ -105,7 +105,7 @@ @DisableFeatures({ChromeFeatureList.NTP_CONDENSED_LAYOUT, ChromeFeatureList.CHROME_HOME, ChromeFeatureList.CONTENT_SUGGESTIONS_SCROLL_TO_LOAD, ChromeFeatureList.NTP_ARTICLE_SUGGESTIONS_EXPANDABLE_HEADER, - ChromeFeatureList.NTP_SHORTCUTS}) + ChromeFeatureList.NTP_SHORTCUTS, ChromeFeatureList.CHROME_DUPLEX}) public class NewTabPageAdapterTest { @Rule public DisableHistogramsRule mDisableHistogramsRule = new DisableHistogramsRule();
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index f910049d..7eb7b50 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2724,10 +2724,6 @@ flag_descriptions::kFramebustingName, flag_descriptions::kFramebustingDescription, kOsAll, FEATURE_VALUE_TYPE(features::kFramebustingNeedsSameOriginOrUserGesture)}, - {"vibrate-requires-user-gesture", - flag_descriptions::kVibrateRequiresUserGestureName, - flag_descriptions::kVibrateRequiresUserGestureDescription, kOsAll, - FEATURE_VALUE_TYPE(features::kVibrateRequiresUserGesture)}, {"web-payments", flag_descriptions::kWebPaymentsName, flag_descriptions::kWebPaymentsDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kWebPayments)},
diff --git a/chrome/browser/devtools/frontend/devtools_discovery_page.html b/chrome/browser/devtools/frontend/devtools_discovery_page.html index d10b8588..2c45611d 100644 --- a/chrome/browser/devtools/frontend/devtools_discovery_page.html +++ b/chrome/browser/devtools/frontend/devtools_discovery_page.html
@@ -1,6 +1,7 @@ <html> <head> <title>Inspectable pages</title> +<meta name="referrer" content="no-referrer"> <style> body { color: #222; @@ -144,8 +145,7 @@ title.className = 'title'; title.textContent = item_object.description || item_object.title; if (item_object.faviconUrl) { - title.style.cssText = 'background-image:url(' + - item_object.faviconUrl + ')'; + title.style.backgroundImage = 'url(' + item_object.faviconUrl + ')'; } description.appendChild(title);
diff --git a/chrome/browser/extensions/active_tab_permission_granter.cc b/chrome/browser/extensions/active_tab_permission_granter.cc index c1134a2..12254cc 100644 --- a/chrome/browser/extensions/active_tab_permission_granter.cc +++ b/chrome/browser/extensions/active_tab_permission_granter.cc
@@ -69,7 +69,8 @@ tab_process->Send(create_message.Run(false)); } -ActiveTabPermissionGranter::Delegate* g_delegate = nullptr; +ActiveTabPermissionGranter::Delegate* g_active_tab_permission_granter_delegate = + nullptr; } // namespace @@ -90,9 +91,9 @@ ActiveTabPermissionGranter::SetPlatformDelegate(Delegate* delegate) { // Disallow setting it twice (but allow resetting - don't forget to free in // that case). - CHECK(!g_delegate || !delegate); - Delegate* previous_delegate = g_delegate; - g_delegate = delegate; + CHECK(!g_active_tab_permission_granter_delegate || !delegate); + Delegate* previous_delegate = g_active_tab_permission_granter_delegate; + g_active_tab_permission_granter_delegate = delegate; return previous_delegate; } @@ -106,8 +107,9 @@ const PermissionsData* permissions_data = extension->permissions_data(); bool should_grant_active_tab = - !g_delegate || - g_delegate->ShouldGrantActiveTab(extension, web_contents()); + !g_active_tab_permission_granter_delegate || + g_active_tab_permission_granter_delegate->ShouldGrantActiveTab( + extension, web_contents()); // If the extension requested all-hosts but has had it withheld, we grant it // active tab-style permissions, even if it doesn't have the activeTab // permission in the manifest.
diff --git a/chrome/browser/extensions/content_verifier_browsertest.cc b/chrome/browser/extensions/content_verifier_browsertest.cc index d36b646..9cc89a5 100644 --- a/chrome/browser/extensions/content_verifier_browsertest.cc +++ b/chrome/browser/extensions/content_verifier_browsertest.cc
@@ -26,6 +26,7 @@ #include "content/public/common/browser_side_navigation_policy.h" #include "content/public/test/test_utils.h" #include "extensions/browser/content_verifier.h" +#include "extensions/browser/content_verifier/test_utils.h" #include "extensions/browser/content_verify_job.h" #include "extensions/browser/crx_file_info.h" #include "extensions/browser/extension_prefs.h" @@ -43,158 +44,6 @@ namespace { -class JobObserver : public ContentVerifyJob::TestObserver { - public: - JobObserver(); - virtual ~JobObserver(); - - enum class Result { SUCCESS, FAILURE }; - - // Call this to add an expected job result. - void ExpectJobResult(const std::string& extension_id, - const base::FilePath& relative_path, - Result expected_result); - - // Wait to see expected jobs. Returns true when we've seen all expected jobs - // finish, or false if there was an error or timeout. - bool WaitForExpectedJobs(); - - // ContentVerifyJob::TestObserver interface - void JobStarted(const ExtensionId& extension_id, - const base::FilePath& relative_path) override; - void JobFinished(const ExtensionId& extension_id, - const base::FilePath& relative_path, - ContentVerifyJob::FailureReason failure_reason) override; - void OnHashesReady(const ExtensionId& extension_id, - const base::FilePath& relative_path, - bool success) override {} - - private: - struct ExpectedResult { - public: - std::string extension_id; - base::FilePath path; - Result result; - - ExpectedResult(const ExtensionId& extension_id, - const base::FilePath& path, - Result result) - : extension_id(extension_id), path(path), result(result) {} - }; - std::list<ExpectedResult> expectations_; - content::BrowserThread::ID creation_thread_; - scoped_refptr<content::MessageLoopRunner> loop_runner_; -}; - -void JobObserver::ExpectJobResult(const std::string& extension_id, - const base::FilePath& relative_path, - Result expected_result) { - expectations_.push_back(ExpectedResult( - extension_id, relative_path, expected_result)); -} - -JobObserver::JobObserver() { - EXPECT_TRUE( - content::BrowserThread::GetCurrentThreadIdentifier(&creation_thread_)); - ContentVerifyJob::SetObserverForTests(this); -} - -JobObserver::~JobObserver() { - ContentVerifyJob::SetObserverForTests(nullptr); -} - -bool JobObserver::WaitForExpectedJobs() { - EXPECT_TRUE(content::BrowserThread::CurrentlyOn(creation_thread_)); - if (!expectations_.empty()) { - loop_runner_ = new content::MessageLoopRunner(); - loop_runner_->Run(); - loop_runner_ = nullptr; - } - return expectations_.empty(); -} - -void JobObserver::JobStarted(const std::string& extension_id, - const base::FilePath& relative_path) { -} - -void JobObserver::JobFinished(const std::string& extension_id, - const base::FilePath& relative_path, - ContentVerifyJob::FailureReason failure_reason) { - if (!content::BrowserThread::CurrentlyOn(creation_thread_)) { - content::BrowserThread::PostTask( - creation_thread_, FROM_HERE, - base::BindOnce(&JobObserver::JobFinished, base::Unretained(this), - extension_id, relative_path, failure_reason)); - return; - } - Result result = failure_reason == ContentVerifyJob::NONE ? Result::SUCCESS - : Result::FAILURE; - bool found = false; - for (std::list<ExpectedResult>::iterator i = expectations_.begin(); - i != expectations_.end(); ++i) { - if (i->extension_id == extension_id && i->path == relative_path && - i->result == result) { - found = true; - expectations_.erase(i); - break; - } - } - if (found) { - if (expectations_.empty() && loop_runner_.get()) - loop_runner_->Quit(); - } else { - LOG(WARNING) << "Ignoring unexpected JobFinished " << extension_id << "/" - << relative_path.value() - << " failure_reason:" << failure_reason; - } -} - -class VerifierObserver : public ContentVerifier::TestObserver { - public: - VerifierObserver(); - virtual ~VerifierObserver(); - - const std::set<std::string>& completed_fetches() { - return completed_fetches_; - } - - // Returns when we've seen OnFetchComplete for |extension_id|. - void WaitForFetchComplete(const std::string& extension_id); - - // ContentVerifier::TestObserver - void OnFetchComplete(const std::string& extension_id, bool success) override; - - private: - std::set<std::string> completed_fetches_; - std::string id_to_wait_for_; - scoped_refptr<content::MessageLoopRunner> loop_runner_; -}; - -VerifierObserver::VerifierObserver() { - ContentVerifier::SetObserverForTests(this); -} - -VerifierObserver::~VerifierObserver() { - ContentVerifier::SetObserverForTests(nullptr); -} - -void VerifierObserver::WaitForFetchComplete(const std::string& extension_id) { - EXPECT_TRUE(id_to_wait_for_.empty()); - EXPECT_EQ(loop_runner_.get(), nullptr); - id_to_wait_for_ = extension_id; - loop_runner_ = new content::MessageLoopRunner(); - loop_runner_->Run(); - id_to_wait_for_.clear(); - loop_runner_ = nullptr; -} - -void VerifierObserver::OnFetchComplete(const std::string& extension_id, - bool success) { - completed_fetches_.insert(extension_id); - if (extension_id == id_to_wait_for_) - loop_runner_->Quit(); -} - // This lets us intercept requests for update checks of extensions, and // substitute a local file as a simulated response. class DownloaderTestDelegate : public ExtensionDownloaderTestDelegate { @@ -365,11 +214,11 @@ // Now disable the extension, since content scripts are read at enable time, // set up our job observer, and re-enable, expecting a success this time. DisableExtension(id); - JobObserver job_observer; + using Result = TestContentVerifyJobObserver::Result; + TestContentVerifyJobObserver job_observer; base::FilePath script_relfilepath = base::FilePath().AppendASCII(script_relpath); - job_observer.ExpectJobResult(id, script_relfilepath, - JobObserver::Result::SUCCESS); + job_observer.ExpectJobResult(id, script_relfilepath, Result::SUCCESS); EnableExtension(id); EXPECT_TRUE(job_observer.WaitForExpectedJobs()); @@ -383,35 +232,31 @@ ASSERT_TRUE(base::AppendToFile(scriptfile, extra.data(), extra.size())); } DisableExtension(id); - job_observer.ExpectJobResult(id, script_relfilepath, - JobObserver::Result::FAILURE); + job_observer.ExpectJobResult(id, script_relfilepath, Result::FAILURE); EnableExtension(id); EXPECT_TRUE(job_observer.WaitForExpectedJobs()); } }; IN_PROC_BROWSER_TEST_F(ContentVerifierTest, DotSlashPaths) { - JobObserver job_observer; + TestContentVerifyJobObserver job_observer; std::string id = "hoipipabpcoomfapcecilckodldhmpgl"; + using Result = TestContentVerifyJobObserver::Result; job_observer.ExpectJobResult( - id, base::FilePath(FILE_PATH_LITERAL("background.js")), - JobObserver::Result::SUCCESS); - job_observer.ExpectJobResult(id, - base::FilePath(FILE_PATH_LITERAL("page.html")), - JobObserver::Result::SUCCESS); + id, base::FilePath(FILE_PATH_LITERAL("background.js")), Result::SUCCESS); + job_observer.ExpectJobResult( + id, base::FilePath(FILE_PATH_LITERAL("page.html")), Result::SUCCESS); job_observer.ExpectJobResult(id, base::FilePath(FILE_PATH_LITERAL("page.js")), - JobObserver::Result::SUCCESS); + Result::SUCCESS); job_observer.ExpectJobResult( - id, base::FilePath(FILE_PATH_LITERAL("dir/page2.html")), - JobObserver::Result::SUCCESS); - job_observer.ExpectJobResult(id, - base::FilePath(FILE_PATH_LITERAL("page2.js")), - JobObserver::Result::SUCCESS); + id, base::FilePath(FILE_PATH_LITERAL("dir/page2.html")), Result::SUCCESS); + job_observer.ExpectJobResult( + id, base::FilePath(FILE_PATH_LITERAL("page2.js")), Result::SUCCESS); job_observer.ExpectJobResult(id, base::FilePath(FILE_PATH_LITERAL("cs1.js")), - JobObserver::Result::SUCCESS); + Result::SUCCESS); job_observer.ExpectJobResult(id, base::FilePath(FILE_PATH_LITERAL("cs2.js")), - JobObserver::Result::SUCCESS); + Result::SUCCESS); VerifierObserver verifier_observer;
diff --git a/chrome/browser/extensions/content_verifier_hash_fetch_behavior_browsertest.cc b/chrome/browser/extensions/content_verifier_hash_fetch_behavior_browsertest.cc new file mode 100644 index 0000000..8e1a611 --- /dev/null +++ b/chrome/browser/extensions/content_verifier_hash_fetch_behavior_browsertest.cc
@@ -0,0 +1,833 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> +#include <string> + +#include "base/macros.h" +#include "chrome/browser/extensions/browsertest_util.h" +#include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/common/chrome_switches.h" +#include "content/public/test/test_utils.h" +#include "extensions/browser/computed_hashes.h" +#include "extensions/browser/content_verifier/test_utils.h" +#include "extensions/browser/extension_file_task_runner.h" +#include "extensions/browser/extension_prefs.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/browser/test_extension_registry_observer.h" +#include "extensions/common/file_util.h" +#include "net/url_request/test_url_request_interceptor.h" + +namespace extensions { + +namespace { + +// Specifies the content verification mode. +enum ContentVerificationMode { + // Uses --extension-content-verification=enforce flag. + kEnforce, + // Uses --extension-content-verification=enforce_strict flag. + kEnforceStrict +}; + +} // namespace + +// Tests content verification's hash fetch behavior and its implication on +// verification failure in different verification modes (enforce and +// enforce_strict). +// TODO(lazyboy): Add assertions for checking verified_contents.json file's +// validity after running each test. +class ContentVerifierHashTest + : public ExtensionBrowserTest, + public testing::WithParamInterface<ContentVerificationMode> { + public: + ContentVerifierHashTest() = default; + ~ContentVerifierHashTest() override {} + + enum TamperResourceType { + kTamperRequestedResource, + kTamperNotRequestedResource + }; + + // ExtensionBrowserTest: + bool ShouldEnableContentVerification() override { return true; } + + void SetUpCommandLine(base::CommandLine* command_line) override { + ExtensionBrowserTest::SetUpCommandLine(command_line); + command_line->AppendSwitchASCII( + switches::kExtensionContentVerification, + uses_enforce_strict_mode() + ? switches::kExtensionContentVerificationEnforceStrict + : switches::kExtensionContentVerificationEnforce); + } + + bool uses_enforce_strict_mode() { + return GetParam() == ContentVerificationMode::kEnforceStrict; + } + bool uses_enforce_mode() { + return GetParam() == ContentVerificationMode::kEnforce; + } + + void DisableHashFetching() { hash_fetching_disabled_ = true; } + + testing::AssertionResult InstallDefaultResourceExtension() { + LOG(INFO) << "InstallDefaultResourceExtension"; + return InstallExtension(kHasDefaultResource); + } + testing::AssertionResult InstallNoDefaultResourceExtension() { + LOG(INFO) << "InstallNoDefaultResourceExtension"; + return InstallExtension(kDoesNotHaveDefaultResource); + } + + void DisableExtension() { ExtensionBrowserTest::DisableExtension(id()); } + + testing::AssertionResult DeleteVerifiedContents() { + base::ScopedAllowBlockingForTesting allow_blocking; + + base::FilePath verified_contents_path = + file_util::GetVerifiedContentsPath(info_->extension_root); + if (!base::PathExists(verified_contents_path)) { + return testing::AssertionFailure() + << "Could not find verified_contents.json."; + } + + // Delete verified_contents.json: + if (!base::DeleteFile(verified_contents_path, false /* recursive */)) { + return testing::AssertionFailure() + << "Could not delete verified_contents.json."; + } + return testing::AssertionSuccess(); + } + + bool HasComputedHashes() { + base::ScopedAllowBlockingForTesting allow_blocking; + return base::PathExists( + file_util::GetComputedHashesPath(info_->extension_root)); + } + + testing::AssertionResult DeleteComputedHashes() { + LOG(INFO) << "Deleting computed_hashes.json"; + base::ScopedAllowBlockingForTesting allow_blocking; + if (!HasComputedHashes()) { + return testing::AssertionFailure() + << "Could not find computed_hashes.json for deletion. " + << "Make sure the previous steps created a " + << "computed_hashes.json, otherwise tests might fail/flake"; + } + base::FilePath computed_hashes_path = + file_util::GetComputedHashesPath(info_->extension_root); + if (!base::DeleteFile(computed_hashes_path, false /* recursive */)) { + return testing::AssertionFailure() + << "Error deleting computed_hashes.json."; + } + return testing::AssertionSuccess(); + } + + testing::AssertionResult TamperComputedHashes() { + LOG(INFO) << "Tampering computed_hashes.json"; + base::ScopedAllowBlockingForTesting allow_blocking; + if (!HasComputedHashes()) { + return testing::AssertionFailure() + << "Could not find computed_hashes.json for tampering."; + } + base::FilePath computed_hashes_path = + file_util::GetComputedHashesPath(info_->extension_root); + std::string extra = R"({hello:"world"})"; + if (!base::AppendToFile(computed_hashes_path, extra.data(), extra.size())) { + return testing::AssertionFailure() + << "Could not tamper computed_hashes.json"; + } + return testing::AssertionSuccess(); + } + + testing::AssertionResult TamperResource(TamperResourceType type) { + const std::string resource_to_tamper = + type == kTamperRequestedResource ? "background.js" : "script.js"; + base::ScopedAllowBlockingForTesting allow_blocking; + // Modify content of a resource if this test requested that, time the + // extension loads, hash fetch will discover content verification failure + // due to hash mismatch. + std::string extra = "some_extra_function_call();"; + base::FilePath real_path = + info_->extension_root.AppendASCII(resource_to_tamper); + if (!base::AppendToFile(real_path, extra.data(), extra.size())) { + return testing::AssertionFailure() + << "Could not tamper " << resource_to_tamper << "."; + } + return testing::AssertionSuccess(); + } + + const ExtensionId& id() const { return info_->extension_id; } + + void EnableExtensionAndWaitForCompletion(bool expect_disabled) { + LOG(INFO) << "EnableExtensionAndWaitForCompletion: expect_disabled = " + << expect_disabled; + // Only observe ContentVerifyJob when necessary. This is because + // ContentVerifyJob's callback and ContentVerifyJob::OnExtensionLoad's + // callbacks can be race-y. + std::unique_ptr<TestContentVerifyJobObserver> job_observer; + const bool needs_to_observe_content_verify_job = + // If the test wouldn't disable the extension, extensions with + // default resource(s) will always see at at least one ContentVerifyJob + // to a default resource (background.js). + info_->type == kHasDefaultResource && !expect_disabled; + + if (needs_to_observe_content_verify_job) { + LOG(INFO) << "Observing ContentVerifyJob"; + job_observer = std::make_unique<TestContentVerifyJobObserver>(); + using Result = TestContentVerifyJobObserver::Result; + job_observer->ExpectJobResult( + id(), base::FilePath(FILE_PATH_LITERAL("background.js")), + Result::SUCCESS); + } + + if (interceptor_) { + EXPECT_EQ(0, interceptor_->GetHitCount()) << "Interceptor should not " + "have seen any requests " + "before enabling extension."; + } + + TestExtensionRegistryObserver registry_observer( + ExtensionRegistry::Get(profile()), id()); + VerifierObserver verifier_observer; + { + EnableExtension(id()); + registry_observer.WaitForExtensionLoaded(); + } + if (!base::ContainsKey(verifier_observer.completed_fetches(), id())) + verifier_observer.WaitForFetchComplete(id()); + LOG(INFO) << "Verifier observer has seen FetchComplete"; + + if (job_observer) { + LOG(INFO) << "ContentVerifyJobObserver, wait for expected job"; + job_observer->WaitForExpectedJobs(); + LOG(INFO) << "ContentVerifyJobObserver, completed expected job"; + } + } + + bool ExtensionIsDisabledForCorruption() { + const Extension* extension = extensions::ExtensionRegistry::Get(profile()) + ->disabled_extensions() + .GetByID(id()); + if (!extension) + return false; + + ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); + // Make sure the extension got disabled due to corruption (and only due to + // corruption). + int reasons = prefs->GetDisableReasons(id()); + return reasons == disable_reason::DISABLE_CORRUPTED; + } + + bool ExtensionIsEnabled() { + return extensions::ExtensionRegistry::Get(profile()) + ->enabled_extensions() + .Contains(id()); + } + + bool HasValidComputedHashes() { + base::ScopedAllowBlockingForTesting allow_blocking; + ComputedHashes::Reader reader; + return reader.InitFromFile( + file_util::GetComputedHashesPath(info_->extension_root)); + } + + bool HasValidVerifiedContents() { + base::ScopedAllowBlockingForTesting allow_blocking; + base::FilePath verified_contents_path = + file_util::GetVerifiedContentsPath(info_->extension_root); + if (!base::PathExists(verified_contents_path)) { + ADD_FAILURE() << "Could not find verified_contents.json."; + return false; + } + std::string contents; + if (!base::ReadFileToString(verified_contents_path, &contents)) { + ADD_FAILURE() << "Could not read verified_contents.json."; + return false; + } + return verified_contents_contents_ == contents; + } + + private: + enum ExtensionType { + // An extension (has_default_resource.crx) that by default requests a + // resource in it during ExtensionLoad. + kHasDefaultResource, + // An extension (no_default_resources.crx) that doesn't request any + // resource during ExtensionLoad. + kDoesNotHaveDefaultResource + }; + + struct ExtensionInfo { + ExtensionId extension_id; + base::FilePath extension_root; + base::Version version; + ExtensionType type; + + ExtensionInfo(const ExtensionId& extension_id, + const base::FilePath& extension_root, + const base::Version& version, + ExtensionType type) + : extension_id(extension_id), + extension_root(extension_root), + version(version), + type(type) {} + ExtensionInfo(const Extension* extension, ExtensionType type) + : ExtensionInfo(extension->id(), + extension->path(), + extension->version(), + type) {} + }; + + // Stores verified_contents.json into a temp file. + bool CopyVerifiedContents(base::FilePath* out_path) { + base::ScopedAllowBlockingForTesting allow_blocking; + if (!temp_dir_.CreateUniqueTempDir()) { + ADD_FAILURE() << "Could not create temp dir for test."; + return false; + } + + base::FilePath verified_contents_path = + file_util::GetVerifiedContentsPath(info_->extension_root); + if (!base::PathExists(verified_contents_path)) { + ADD_FAILURE() << "Could not find verified_contents.json for copying."; + return false; + } + base::FilePath destination = temp_dir_.GetPath(); + *out_path = destination.Append(FILE_PATH_LITERAL("copy.json")); + if (!base::CopyFile(verified_contents_path, *out_path)) { + ADD_FAILURE() << "Could not copy verified_contents.json to a temp dir."; + return false; + } + if (!base::ReadFileToString(verified_contents_path, + &verified_contents_contents_)) { + ADD_FAILURE() << "Could not read verified_contents.json."; + return false; + } + return true; + } + + bool AddInterceptor() { + if (interceptor_) { + ADD_FAILURE() << "Already created interceptor."; + return false; + } + + // Use stored copy of verified_contents.json as hash fetch response. + base::FilePath copied_verified_contents_path; + if (!CopyVerifiedContents(&copied_verified_contents_path)) { + ADD_FAILURE() << "Could not copy verified_contents.json."; + return false; + } + + ExtensionSystem* system = ExtensionSystem::Get(profile()); + GURL fetch_url = system->content_verifier()->GetSignatureFetchUrlForTest( + id(), info_->version); + + // Mock serving |copied_verified_contents_path| for content hash, so that + // hash fetch succeeds. + interceptor_ = std::make_unique<net::TestURLRequestInterceptor>( + fetch_url.scheme(), fetch_url.host(), + content::BrowserThread::GetTaskRunnerForThread( + content::BrowserThread::IO), + GetExtensionFileTaskRunner()); + interceptor_->SetResponse(fetch_url, copied_verified_contents_path); + return true; + } + + // Installs test extension that is copied from the webstore with actual + // signatures. + testing::AssertionResult InstallExtension(ExtensionType type) { + // This observer will make sure content hash read and computed_hashes.json + // writing is complete before we proceed. + VerifierObserver verifier_observer; + + const std::string crx_relative_path = + type == kHasDefaultResource + ? "content_verifier/has_default_resource.crx" + : "content_verifier/no_default_resources.crx"; + // These test extension is copied from the webstore that has actual + // signatures. + const Extension* extension = InstallExtensionFromWebstore( + test_data_dir_.AppendASCII(crx_relative_path), 1); + if (!extension) { + return testing::AssertionFailure() + << "Could not install extension: " << crx_relative_path; + } + + const ExtensionId& extension_id = extension->id(); + if (!base::ContainsKey(verifier_observer.completed_fetches(), extension_id)) + verifier_observer.WaitForFetchComplete(extension_id); + + info_ = std::make_unique<ExtensionInfo>(extension, type); + + // Interceptor. + if (!hash_fetching_disabled_ && !AddInterceptor()) + return testing::AssertionFailure() << "Failed to install interceptor."; + + return testing::AssertionSuccess(); + } + + std::unique_ptr<net::TestURLRequestInterceptor> interceptor_; + base::ScopedTempDir temp_dir_; + + // Information about the loaded extension. + std::unique_ptr<ExtensionInfo> info_; + + // Contents of verified_contents.json (if available). + std::string verified_contents_contents_; + + bool hash_fetching_disabled_ = false; + + DISALLOW_COPY_AND_ASSIGN(ContentVerifierHashTest); +}; + +// Tests that corruption of a requested extension resource always disables the +// extension. +IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest, + TamperRequestedResourceKeepComputedHashes) { + ASSERT_TRUE(InstallDefaultResourceExtension()); + + DisableExtension(); + + // Delete verified_contents.json to force a hash fetch on next load. + EXPECT_TRUE(DeleteVerifiedContents()); + + // computed_hashes.json should remain valid. + EXPECT_TRUE(HasComputedHashes()); + + // Tamper an extension resource that will be requested on next load. + EXPECT_TRUE(TamperResource(kTamperRequestedResource)); + + TestExtensionRegistryObserver registry_observer( + ExtensionRegistry::Get(profile()), id()); + // Since we tampered with the resource, content verification should + // disable the extension, both in "enforce_strict" and "enforce" mode. + EnableExtensionAndWaitForCompletion(true /* expect_disabled */); + EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded()); + + EXPECT_TRUE(ExtensionIsDisabledForCorruption()); + + // Expect a valid verified_contents.json file at the end. + EXPECT_TRUE(HasValidVerifiedContents()); +} + +// Tests that tampering a resource that will be requested by the extension and +// deleting computed_hashes.json will always disable the extension. +IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest, + TamperRequestedResourceDeleteComputedHashes) { + ASSERT_TRUE(InstallDefaultResourceExtension()); + + DisableExtension(); + + // Delete verified_contents.json to force a hash fetch on next load. + EXPECT_TRUE(DeleteVerifiedContents()); + + // Delete computed_hashes.json. + EXPECT_TRUE(DeleteComputedHashes()); + + // Tamper an extension resource that will be requested on next load. + EXPECT_TRUE(TamperResource(kTamperRequestedResource)); + + TestExtensionRegistryObserver registry_observer( + ExtensionRegistry::Get(profile()), id()); + // Since we tampered with the resource, content verification should + // disable the extension, both in "enforce_strict" and "enforce" mode. + EnableExtensionAndWaitForCompletion(true /* expect_disabled */); + EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded()); + + EXPECT_TRUE(ExtensionIsDisabledForCorruption()); + + // Expect a valid computed_hashes.json file at the end, the verification + // failure must have used this file to detect corruption. + EXPECT_TRUE(HasValidComputedHashes()); + + // Expect a valid verified_contents.json file at the end. + EXPECT_TRUE(HasValidVerifiedContents()); +} + +// Tests that tampering a resource that will be requested by the extension and +// tampering computed_hashes.json will always disable the extension. +IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest, + TamperRequestedResourceTamperComputedHashes) { + ASSERT_TRUE(InstallDefaultResourceExtension()); + + DisableExtension(); + + // Delete verified_contents.json to force a hash fetch on next load. + EXPECT_TRUE(DeleteVerifiedContents()); + + // Tamper computed_hashes.json. + EXPECT_TRUE(TamperComputedHashes()); + + // Tamper an extension resource that will be requested on next load. + EXPECT_TRUE(TamperResource(kTamperRequestedResource)); + + TestExtensionRegistryObserver registry_observer( + ExtensionRegistry::Get(profile()), id()); + // Since we tampered with the resource, content verification should + // disable the extension, both in "enforce_strict" and "enforce" mode. + EnableExtensionAndWaitForCompletion(true /* expect_disabled */); + EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded()); + + EXPECT_TRUE(ExtensionIsDisabledForCorruption()); + + // Expect a valid computed_hashes.json file at the end, the verification + // failure must have used this file to detect corruption. + EXPECT_TRUE(HasValidComputedHashes()); + + // Expect a valid verified_contents.json file at the end. + EXPECT_TRUE(HasValidVerifiedContents()); +} + +// Tests hash fetch failure scenario with an extension that requests resource(s) +// by default. +IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest, + FetchFailureWithDefaultResourceExtension) { + // Do *not* install any hash fetch interceptor, so that hash fetch after + // reload fails. + DisableHashFetching(); + + ASSERT_TRUE(InstallDefaultResourceExtension()); + + DisableExtension(); + + // Delete verified_contents.json to force a hash fetch on next load. + EXPECT_TRUE(DeleteVerifiedContents()); + + // computed_hashes.json and extension resource(s) aren't touched since they do + // not matter as hash fetch will fail. + + // In "enforce_strict" mode, hash fetch failures will cause the extension to + // be disabled. Implementation-wise, this happens because the requested + // resource's ContentVerifyJob will result in failure, not because the hash + // fetch failed. See https://crbug.com/819818 for details. + // + // In "enforce" mode, the extension won't be disabled. However, since we + // request a resource (background.js), its corresponding ContentVerifyJob will + // attempt to fetch hash and that job will also fail. In order to achieve + // determinism in this case, also observe a ContentVerifyJob that will fail. + const bool expect_disabled = uses_enforce_strict_mode(); + + // Similar to EnableExtensionAndWaitForCompletion, but also forces a + // ContentVerifyJob observer in "enforce" mode. + // Instead of generalizing this oddball expectation into + // EnableExtensionAndWaitForCompletion, provide the implementation right here + // in the test body. + { + LOG(INFO) << "EnableExtensionAndWaitForCompletion: expect_disabled = " + << expect_disabled; + ExtensionId extension_id = id(); + + // Only observe ContentVerifyJob when necessary. This is because + // ContentVerifyJob's callback and ContentVerifyJob::OnExtensionLoad's + // callbacks can be race-y. + std::unique_ptr<TestContentVerifyJobObserver> job_observer; + if (uses_enforce_mode()) { + // In "enforce" mode, we expect to see a job completion (and its failure). + job_observer = std::make_unique<TestContentVerifyJobObserver>(); + using Result = TestContentVerifyJobObserver::Result; + job_observer->ExpectJobResult( + extension_id, + // This extension has default resource (background.js), so it must + // request it. + base::FilePath(FILE_PATH_LITERAL("background.js")), Result::FAILURE); + } + + TestExtensionRegistryObserver registry_observer( + ExtensionRegistry::Get(profile()), extension_id); + VerifierObserver verifier_observer; + { + EnableExtension(extension_id); + registry_observer.WaitForExtensionLoaded(); + } + if (!base::ContainsKey(verifier_observer.completed_fetches(), extension_id)) + verifier_observer.WaitForFetchComplete(extension_id); + LOG(INFO) << "Verifier observer has seen FetchComplete"; + + if (job_observer) { + LOG(INFO) << "ContentVerifyJobObserver, wait for expected job"; + job_observer->WaitForExpectedJobs(); + LOG(INFO) << "ContentVerifyJobObserver, completed expected job"; + } + + if (expect_disabled) + EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded()); + } + + EXPECT_TRUE(expect_disabled ? ExtensionIsDisabledForCorruption() + : ExtensionIsEnabled()); +} + +// Tests that hash fetch failure for loading an extension that doesn't request +// any resource by default will not be disabled. +IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest, + FetchFailureWithNoDefaultResourceDoesNotDisable) { + // Do *not* install any hash fetch interceptor, so that hash fetch after + // reload fails. + DisableHashFetching(); + + ASSERT_TRUE(InstallNoDefaultResourceExtension()); + + DisableExtension(); + + // Delete verified_contents.json to force a hash fetch on next load. + EXPECT_TRUE(DeleteVerifiedContents()); + + // computed_hashes.json and extension resource(s) aren't touched since they do + // not matter as hash fetch will fail. + + // If the extension didn't explicitly request any resources, then there will + // not be any content verification failures. + const bool expect_disabled = false; + // TODO(lazyboy): https://crbug.com/819818: "enforce_strict" mode should + // disable the extension. + // const bool expect_disabled = uses_enforce_strict_mode(); + EnableExtensionAndWaitForCompletion(expect_disabled); + + EXPECT_TRUE(expect_disabled ? ExtensionIsDisabledForCorruption() + : ExtensionIsEnabled()); +} + +// Tests the behavior of tampering an extension resource that is not requested +// by default and without modifying computed_hashes.json. +IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest, + TamperNotRequestedResourceKeepComputedHashes) { + ASSERT_TRUE(InstallDefaultResourceExtension()); + + DisableExtension(); + + // Delete verified_contents.json to force a hash fetch on next load. + EXPECT_TRUE(DeleteVerifiedContents()); + + // computed_hashes.json should remain valid. + EXPECT_TRUE(HasComputedHashes()); + + // Tamper an extension resource that will *not* be requested on next load. + EXPECT_TRUE(TamperResource(kTamperNotRequestedResource)); + + // We tampered a resource that is not requested by the extension. Keeping + // computed_hashes.json will not compute new compute computed_hashes.json, and + // we will not discover the tampered hash. So the extension won't be disabled. + // + // TODO(lazyboy): http://crbug.com/819832: We fetched a new + // verified_contents.json in this case. However, if we had recomputed + // computed_hashes.json we would have discovered the tampered resource's hash + // mismatch. Fix. + const bool expect_disabled = false; + EnableExtensionAndWaitForCompletion(expect_disabled); + + EXPECT_TRUE(ExtensionIsEnabled()); + + // Expect a valid verified_contents.json file at the end. + EXPECT_TRUE(HasValidVerifiedContents()); +} + +// Tests the behavior of loading an extension without any default resource +// request and deleting its computed_hashes.json before fetching hashes. +IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest, + TamperNoResourceExtensionDeleteComputedHashes) { + ASSERT_TRUE(InstallNoDefaultResourceExtension()); + + DisableExtension(); + + // Delete verified_contents.json to force a hash fetch on next load. + EXPECT_TRUE(DeleteVerifiedContents()); + + // Delete computed_hashes.json. + EXPECT_TRUE(DeleteComputedHashes()); + + // Tamper an extension resource that will *not* be requested on next load. + EXPECT_TRUE(TamperResource(kTamperNotRequestedResource)); + + TestExtensionRegistryObserver registry_observer( + ExtensionRegistry::Get(profile()), id()); + // The deletion of computed_hashes.json forces its recomputation and disables + // the extension. + EnableExtensionAndWaitForCompletion(true /* expect_disabled */); + EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded()); + + EXPECT_TRUE(ExtensionIsDisabledForCorruption()); + + // Expect a valid computed_hashes.json file at the end, the verification + // failure must have used this file to detect corruption. + EXPECT_TRUE(HasValidComputedHashes()); + + // Expect a valid verified_contents.json file at the end. + EXPECT_TRUE(HasValidVerifiedContents()); +} + +// Tests the behavior of loading an extension without any default resource +// request and keeping its computed_hashes.json. +IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest, + TamperNoResourceExtensionKeepComputedHashes) { + ASSERT_TRUE(InstallNoDefaultResourceExtension()); + + DisableExtension(); + + // Delete verified_contents.json to force a hash fetch on next load. + EXPECT_TRUE(DeleteVerifiedContents()); + + // computed_hashes.json should remain valid. + EXPECT_TRUE(HasComputedHashes()); + + // Tamper an extension resource that will *not* be requested on next load. + EXPECT_TRUE(TamperResource(kTamperNotRequestedResource)); + + // Not modifying computed_hashes.json will not trigger any hash computation + // at OnExtensionLoad, so we won't discover any hash mismatches. + EnableExtensionAndWaitForCompletion(false /* expect_disabled */); + + EXPECT_TRUE(ExtensionIsEnabled()); + + // Expect a valid verified_contents.json file at the end. + EXPECT_TRUE(HasValidVerifiedContents()); +} + +// Tests the behavior of loading an extension without any default resource +// request and tampering its computed_hashes.json. +IN_PROC_BROWSER_TEST_P(ContentVerifierHashTest, + TamperNoResourceExtensionTamperComputedHashes) { + ASSERT_TRUE(InstallNoDefaultResourceExtension()); + + DisableExtension(); + + // Delete verified_contents.json to force a hash fetch on next load. + EXPECT_TRUE(DeleteVerifiedContents()); + + // Tamper computed_hashes.json. + EXPECT_TRUE(TamperComputedHashes()); + + // Tamper an extension resource that will *not* be requested on next load. + EXPECT_TRUE(TamperResource(kTamperNotRequestedResource)); + + // Tampering computed_hashes.json will not trigger any hash computation + // at OnExtensionLoad, so we won't discover any hash mismatches. + // TODO(lazyboy): Consider fixing this, see http://crbug.com/819832 for + // details. + EnableExtensionAndWaitForCompletion(false /* expect_disabled */); + + EXPECT_TRUE(ExtensionIsEnabled()); + + // Because we didn't do any hash computation, expect computed_hashes.json to + // still remain invalid. + EXPECT_FALSE(HasValidComputedHashes()); + + // Expect a valid verified_contents.json file at the end. + EXPECT_TRUE(HasValidVerifiedContents()); +} + +// Tests the behavior of loading a default resource extension with tampering +// an extension resource that is not requested by default and without modifying +// computed_hashes.json. +IN_PROC_BROWSER_TEST_P( + ContentVerifierHashTest, + DefaultRequestExtensionTamperNotRequestedResourceKeepComputedHashes) { + ASSERT_TRUE(InstallDefaultResourceExtension()); + + DisableExtension(); + + // Delete verified_contents.json to force a hash fetch on next load. + EXPECT_TRUE(DeleteVerifiedContents()); + + // computed_hashes.json should remain valid. + EXPECT_TRUE(HasComputedHashes()); + + // Tamper an extension resource that will *not* be requested on next load. + EXPECT_TRUE(TamperResource(kTamperNotRequestedResource)); + + // TODO(lazyboy): Not modifying the computed_hashes.json file doesn't prompt + // a hash recomputation and the requested (not-tampered) resource's + // corresponding ContentVerifyJob succeeds because that resource's hash + // remains fine. Therefore, the extension remains enabled. Consider disabling + // the extension in this case: https://crbug.com/819832. + EnableExtensionAndWaitForCompletion(false /* expect_disabled */); + + EXPECT_TRUE(ExtensionIsEnabled()); + + // Expect a valid verified_contents.json file at the end. + EXPECT_TRUE(HasValidVerifiedContents()); +} + +// Tests the behavior of loading a default resource extension with tampering +// an extension resource that is not requested by default and tampering +// computed_hashes.json. +IN_PROC_BROWSER_TEST_P( + ContentVerifierHashTest, + DefaultRequestExtensionTamperNotRequestedResourceTamperComputedHashes) { + ASSERT_TRUE(InstallDefaultResourceExtension()); + + DisableExtension(); + + // Delete verified_contents.json to force a hash fetch on next load. + EXPECT_TRUE(DeleteVerifiedContents()); + + // Tamper computed_hashes.json. + EXPECT_TRUE(TamperComputedHashes()); + + // Tamper an extension resource that will *not* be requested on next load. + EXPECT_TRUE(TamperResource(kTamperNotRequestedResource)); + + TestExtensionRegistryObserver registry_observer( + ExtensionRegistry::Get(profile()), id()); + // Subtle: tampering computed_hashes.json (by itself) will not trigger any + // hash computation or failure during OnExtensionLoad. However, the default + // resource request (that isn't tampered) will prompt a hash read that will + // fail due to the tampered computed_hashes.json. + EnableExtensionAndWaitForCompletion(true /* expect_disabled */); + EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded()); + + EXPECT_TRUE(ExtensionIsDisabledForCorruption()); + + // Expect a valid computed_hashes.json file at the end, the verification + // failure must have used this file to detect corruption. + EXPECT_TRUE(HasValidComputedHashes()); + + // Expect a valid verified_contents.json file at the end. + EXPECT_TRUE(HasValidVerifiedContents()); +} + +// Tests the behavior of loading a default resource extension with tampering +// an extension resource that is not requested by default and deleting +// computed_hashes.json. +IN_PROC_BROWSER_TEST_P( + ContentVerifierHashTest, + DefaultRequestExtensionTamperNotRequestedResourceDeleteComputedHashes) { + ASSERT_TRUE(InstallDefaultResourceExtension()); + + DisableExtension(); + + // Delete verified_contents.json to force a hash fetch on next load. + EXPECT_TRUE(DeleteVerifiedContents()); + + // Delete computed_hashes.json. + EXPECT_TRUE(DeleteComputedHashes()); + + // Tamper an extension resource that will *not* be requested on next load. + EXPECT_TRUE(TamperResource(kTamperNotRequestedResource)); + + TestExtensionRegistryObserver registry_observer( + ExtensionRegistry::Get(profile()), id()); + // The deletion of computed_hashes.json will trigger hash recomputation and + // the file's regeneration. This will discover the resource tampering and + // disable the extension. + EnableExtensionAndWaitForCompletion(true /* expect_disabled */); + EXPECT_TRUE(registry_observer.WaitForExtensionUnloaded()); + + EXPECT_TRUE(ExtensionIsDisabledForCorruption()); + + // Expect a valid computed_hashes.json file at the end, the verification + // failure must have used this file to detect corruption. + EXPECT_TRUE(HasValidComputedHashes()); + + // Expect a valid verified_contents.json file at the end. + EXPECT_TRUE(HasValidVerifiedContents()); +} + +INSTANTIATE_TEST_CASE_P(FetchBehaviorTests, + ContentVerifierHashTest, + testing::Values(kEnforce, kEnforceStrict)); + +} // namespace extensions
diff --git a/chrome/browser/extensions/extension_protocols_unittest.cc b/chrome/browser/extensions/extension_protocols_unittest.cc index 20497429..c49bb9b 100644 --- a/chrome/browser/extensions/extension_protocols_unittest.cc +++ b/chrome/browser/extensions/extension_protocols_unittest.cc
@@ -562,7 +562,7 @@ // Valid and readable 1024.js. { - TestContentVerifyJobObserver observer(extension_id, kRelativePath); + TestContentVerifySingleJobObserver observer(extension_id, kRelativePath); content_verifier_->OnExtensionLoaded(browser_context(), extension.get()); // Wait for PostTask to ContentVerifierIOData::AddData() to finish. @@ -574,7 +574,7 @@ // chmod -r 1024.js. { - TestContentVerifyJobObserver observer(extension->id(), kRelativePath); + TestContentVerifySingleJobObserver observer(extension->id(), kRelativePath); base::FilePath file_path = unzipped_path.AppendASCII(kJs); ASSERT_TRUE(base::MakeFileUnreadable(file_path)); EXPECT_EQ(net::ERR_ACCESS_DENIED, DoRequestOrLoad(extension, kJs).result()); @@ -588,7 +588,7 @@ // Delete 1024.js. { - TestContentVerifyJobObserver observer(extension_id, kRelativePath); + TestContentVerifySingleJobObserver observer(extension_id, kRelativePath); base::FilePath file_path = unzipped_path.AppendASCII(kJs); ASSERT_TRUE(base::DieFileDie(file_path, false)); EXPECT_EQ(net::ERR_FILE_NOT_FOUND, @@ -623,7 +623,7 @@ // Request empty.js. { - TestContentVerifyJobObserver observer(extension_id, kRelativePath); + TestContentVerifySingleJobObserver observer(extension_id, kRelativePath); content_verifier_->OnExtensionLoaded(browser_context(), extension.get()); // Wait for PostTask to ContentVerifierIOData::AddData() to finish. @@ -638,7 +638,7 @@ // current behavior of ContentVerifyJob. // TODO(lazyboy): The behavior is probably incorrect. { - TestContentVerifyJobObserver observer(extension->id(), kRelativePath); + TestContentVerifySingleJobObserver observer(extension->id(), kRelativePath); base::FilePath file_path = unzipped_path.AppendASCII(kEmptyJs); ASSERT_TRUE(base::MakeFileUnreadable(file_path)); EXPECT_EQ(net::ERR_ACCESS_DENIED, @@ -651,7 +651,7 @@ // current behavior of ContentVerifyJob. // TODO(lazyboy): The behavior is probably incorrect. { - TestContentVerifyJobObserver observer(extension_id, kRelativePath); + TestContentVerifySingleJobObserver observer(extension_id, kRelativePath); base::FilePath file_path = unzipped_path.AppendASCII(kEmptyJs); ASSERT_TRUE(base::DieFileDie(file_path, false)); EXPECT_EQ(net::ERR_FILE_NOT_FOUND,
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc index f7691554..bc0755e 100644 --- a/chrome/browser/extensions/extension_tab_util.cc +++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -104,7 +104,7 @@ return SessionTabHelper::IdForTab(web_contents); } -ExtensionTabUtil::Delegate* g_delegate = nullptr; +ExtensionTabUtil::Delegate* g_extension_tab_util_delegate = nullptr; } // namespace @@ -476,8 +476,8 @@ void ExtensionTabUtil::SetPlatformDelegate(Delegate* delegate) { // Allow setting it only once (also allow reset to nullptr, but then take // special care to free it). - CHECK(!g_delegate || !delegate); - g_delegate = delegate; + CHECK(!g_extension_tab_util_delegate || !delegate); + g_extension_tab_util_delegate = delegate; } // static @@ -507,8 +507,9 @@ tab->title.reset(); tab->fav_icon_url.reset(); } - if (g_delegate) - g_delegate->ScrubTabForExtension(extension, contents, tab); + if (g_extension_tab_util_delegate) + g_extension_tab_util_delegate->ScrubTabForExtension(extension, contents, + tab); } bool ExtensionTabUtil::GetTabStripModel(const WebContents* web_contents,
diff --git a/chrome/browser/external_protocol/external_protocol_handler.cc b/chrome/browser/external_protocol/external_protocol_handler.cc index 9bd2997..681b280 100644 --- a/chrome/browser/external_protocol/external_protocol_handler.cc +++ b/chrome/browser/external_protocol/external_protocol_handler.cc
@@ -30,7 +30,8 @@ // each user gesture. This variable should only be accessed from the UI thread. bool g_accept_requests = true; -ExternalProtocolHandler::Delegate* g_delegate = nullptr; +ExternalProtocolHandler::Delegate* g_external_protocol_handler_delegate = + nullptr; constexpr const char* kDeniedSchemes[] = { "afp", "data", "disk", "disks", @@ -147,7 +148,7 @@ // static void ExternalProtocolHandler::SetDelegateForTesting(Delegate* delegate) { - g_delegate = delegate; + g_external_protocol_handler_delegate = delegate; } // static @@ -237,11 +238,11 @@ Profile* profile = nullptr; if (web_contents) // Maybe NULL during testing. profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); - BlockState block_state = - GetBlockStateWithDelegate(escaped_url.scheme(), g_delegate, profile); + BlockState block_state = GetBlockStateWithDelegate( + escaped_url.scheme(), g_external_protocol_handler_delegate, profile); if (block_state == BLOCK) { - if (g_delegate) - g_delegate->BlockRequest(); + if (g_external_protocol_handler_delegate) + g_external_protocol_handler_delegate->BlockRequest(); return; } @@ -252,12 +253,13 @@ shell_integration::DefaultWebClientWorkerCallback callback = base::Bind( &OnDefaultProtocolClientWorkerFinished, escaped_url, render_process_host_id, render_view_routing_id, block_state == UNKNOWN, - page_transition, has_user_gesture, g_delegate); + page_transition, has_user_gesture, g_external_protocol_handler_delegate); // Start the check process running. This will send tasks to a worker task // runner and when the answer is known will send the result back to // OnDefaultProtocolClientWorkerFinished(). - CreateShellWorker(callback, escaped_url.scheme(), g_delegate) + CreateShellWorker(callback, escaped_url.scheme(), + g_external_protocol_handler_delegate) ->StartCheckIsDefault(); }
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 9b28b25..3868223 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1640,12 +1640,6 @@ "This enables upcoming and experimental V8 VM features. " "This flag does not enable experimental JavaScript features."; -const char kVibrateRequiresUserGestureName[] = - "Requiring user gesture for the Vibration API"; -const char kVibrateRequiresUserGestureDescription[] = - "Block the Vibration API if no user gesture has been received on the frame " - "or any embedded frame."; - const char kVideoFullscreenOrientationLockName[] = "Lock screen orientation when playing a video fullscreen."; const char kVideoFullscreenOrientationLockDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 20cab74..4d67f3d 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1002,9 +1002,6 @@ extern const char kV8VmFutureName[]; extern const char kV8VmFutureDescription[]; -extern const char kVibrateRequiresUserGestureName[]; -extern const char kVibrateRequiresUserGestureDescription[]; - extern const char kVideoFullscreenOrientationLockName[]; extern const char kVideoFullscreenOrientationLockDescription[];
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index 20b9d28..44d7c88 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -123,6 +123,7 @@ #include "components/policy/core/common/policy_types.h" #include "components/policy/policy_constants.h" #include "components/prefs/pref_service.h" +#include "components/safe_browsing/features.h" #include "components/search_engines/template_url.h" #include "components/search_engines/template_url_service.h" #include "components/security_interstitials/content/security_interstitial_page.h" @@ -3982,6 +3983,9 @@ // Test that when password protection warning trigger is set by policy, chrome // password protection service gets the correct value. IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionWarningTrigger) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + safe_browsing::kEnterprisePasswordProtectionV1); // Without setting up the enterprise policy, // |GetPasswordProtectionTriggerPref(..) should return |PHISHING_REUSE|. const PrefService* const prefs = browser()->profile()->GetPrefs(); @@ -4019,6 +4023,9 @@ // Test that when password protection risk trigger is set by policy, chrome // password protection service gets the correct value. IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionRiskTrigger) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + safe_browsing::kEnterprisePasswordProtectionV1); // Without setting up the enterprise policy, // |GetPasswordProtectionTriggerPref(..) should return |PHISHING_REUSE|. const PrefService* const prefs = browser()->profile()->GetPrefs(); @@ -4056,6 +4063,9 @@ // Test that when safe browsing whitelist domains are set by policy, safe // browsing service gets the correct value. IN_PROC_BROWSER_TEST_F(PolicyTest, SafeBrowsingWhitelistDomains) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + safe_browsing::kEnterprisePasswordProtectionV1); // Without setting up the enterprise policy, // |GetSafeBrowsingDomainsPref(..) should return empty list. const PrefService* const prefs = browser()->profile()->GetPrefs(); @@ -4101,6 +4111,9 @@ // Test that when password protection login URLs are set by policy, password // protection service gets the correct value. IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionLoginURLs) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + safe_browsing::kEnterprisePasswordProtectionV1); // Without setting up the enterprise policy, // |GetPasswordProtectionLoginURLsPref(..) should return empty list. const PrefService* const prefs = browser()->profile()->GetPrefs(); @@ -4144,6 +4157,9 @@ // Test that when password protection change password URL is set by policy, // password protection service gets the correct value. IN_PROC_BROWSER_TEST_F(PolicyTest, PasswordProtectionChangePasswordURL) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + safe_browsing::kEnterprisePasswordProtectionV1); // Without setting up the enterprise policy, // |GetChangePasswordURL(..) should return default GAIA change password URL. const PrefService* const prefs = browser()->profile()->GetPrefs();
diff --git a/chrome/browser/resources/policy_tool.css b/chrome/browser/resources/policy_tool.css index 7ddad45a..d62e867 100644 --- a/chrome/browser/resources/policy_tool.css +++ b/chrome/browser/resources/policy_tool.css
@@ -32,6 +32,13 @@ display: block; } +#session-rename-error { + display: block; + color: red; + margin: 20px; + text-align: center; +} + #session-list { background: white; } @@ -43,3 +50,22 @@ #session-actions { float: left; } + +#session-actions button { + display: block; + width: 80px; +} + +#rename-dialog { + border: 3px black; + height: 130px; + outline: 2px solid DarkGrey; + text-align: center; + width: 300px; +} + +#new-session-name-field { + display: block; + margin: 20px auto; + width: 250px +}
diff --git a/chrome/browser/resources/policy_tool.html b/chrome/browser/resources/policy_tool.html index 12b6227..e2d27feb 100644 --- a/chrome/browser/resources/policy_tool.html +++ b/chrome/browser/resources/policy_tool.html
@@ -31,6 +31,8 @@ <h1>$i18n{title}</h1> </header> <section class="reload-show-unset-section"> + <h1 id="session-title"> + </h1> <form id="session-choice"> <input id="session-name-field" type="text" autocomplete="off" placeholder="$i18n{sessionNamePlaceholder}"> @@ -51,8 +53,15 @@ </span> </section> <section id="sessions"> + <dialog id="rename-dialog"> + <input id="new-session-name-field" type="text"> + <button id="cancel-rename-button">$i18n{cancelRename}</button> + <button id="confirm-rename-button">$i18n{confirmRename}</button> + <span id="session-rename-error" hidden></span> + </dialog> <div id="session-actions"> - <button id="delete-session-button">-</button> + <button id="delete-session-button">$i18n{removeSession}</button> + <button id="rename-session-button">$i18n{renameSession}</button> </div> <select size="4" id="session-list"> </select>
diff --git a/chrome/browser/resources/policy_tool.js b/chrome/browser/resources/policy_tool.js index c3e321c..67bcba9d 100644 --- a/chrome/browser/resources/policy_tool.js +++ b/chrome/browser/resources/policy_tool.js
@@ -21,6 +21,10 @@ } }; +policy.Page.setSessionTitle = function(name) { + $('session-title').textContent = name; +}; + // Override some methods of policy.Page. /** @@ -31,6 +35,23 @@ }; /** + * Shows error message of rename session. + */ +policy.Page.showRenameSessionError = function(errorMessage) { + $('session-rename-error').hidden = false; + $('session-rename-error').textContent = errorMessage; +}; + +/** + * Close dialog of rename session. + */ +policy.Page.closeRenameSessionDialog = function() { + $('session-rename-error').textContent = ''; + $('session-rename-error').hidden = true; + $('rename-dialog').close(); +}; + +/** * Disables editing policy values by hiding the main section and shows an * error message instead. */ @@ -116,6 +137,29 @@ } }; + $('rename-session-button').onclick = () => { + $('session-rename-error').hidden = true; + var sessionName = $('session-list').value; + if (sessionName) { + $('rename-dialog').showModal(); + $('new-session-name-field').value = ''; + $('new-session-name-field').select(); + } + }; + + $('cancel-rename-button').onclick = () => { + $('rename-dialog').close(); + }; + + $('confirm-rename-button').onclick = () => { + $('session-rename-error').textContent = ''; + var sessionName = $('session-list').value; + var newSessionName = $('new-session-name-field').value; + if (sessionName && newSessionName) { + chrome.send('renameSession', [sessionName, newSessionName]); + } + }; + // Notify the browser that the page has loaded, causing it to send the // list of all known policies and the values from the default session. chrome.send('initialized');
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service.cc b/chrome/browser/safe_browsing/certificate_reporting_service.cc index 9725da7..5cad9ff7 100644 --- a/chrome/browser/safe_browsing/certificate_reporting_service.cc +++ b/chrome/browser/safe_browsing/certificate_reporting_service.cc
@@ -14,7 +14,7 @@ #include "components/prefs/pref_service.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" #include "content/public/browser/browser_thread.h" -#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" +#include "net/traffic_annotation/network_traffic_annotation.h" namespace { @@ -321,8 +321,28 @@ std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter; if (server_public_key) { // Only used in tests. - std::unique_ptr<net::ReportSender> report_sender(new net::ReportSender( - url_request_context, TRAFFIC_ANNOTATION_FOR_TESTS)); + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation( + "certificate_reporting_service_test", R"( + semantics { + sender: "Certificate Reporting Service Test" + description: + "This request is used for testing certificate reporting service." + trigger: "Upon request from testing API." + data: + "No user data." + destination: GOOGLE_OWNED_SERVICE + } + policy { + cookies_allowed: NO + setting: + "This feature is only used for testing." + policy_exception_justification: + "This feature is only used for testing." + } + )"); + std::unique_ptr<net::ReportSender> report_sender( + new net::ReportSender(url_request_context, traffic_annotation)); error_reporter.reset(new certificate_reporting::ErrorReporter( GURL(kExtendedReportingUploadUrl), server_public_key, server_public_key_version, std::move(report_sender)));
diff --git a/chrome/browser/signin/signin_ui_util.cc b/chrome/browser/signin/signin_ui_util.cc index a3555999..2a84d57 100644 --- a/chrome/browser/signin/signin_ui_util.cc +++ b/chrome/browser/signin/signin_ui_util.cc
@@ -152,28 +152,33 @@ #if BUILDFLAG(ENABLE_DICE_SUPPORT) // TODO(tangltom): Add a unit test for this function. std::vector<AccountInfo> GetAccountsForDicePromos(Profile* profile) { - SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile); - DCHECK(!signin_manager->IsAuthenticated()); - // Fetch account ids for accounts that have a token. ProfileOAuth2TokenService* token_service = ProfileOAuth2TokenServiceFactory::GetForProfile(profile); std::vector<std::string> account_ids = token_service->GetAccounts(); - // Fetch accounts in the Gaia cookies. - GaiaCookieManagerService* cookie_manager_service = - GaiaCookieManagerServiceFactory::GetForProfile(profile); - std::vector<gaia::ListedAccount> cookie_accounts; - bool gaia_accounts_stale = !cookie_manager_service->ListAccounts( - &cookie_accounts, nullptr, "ProfileChooserView"); - UMA_HISTOGRAM_BOOLEAN("Profile.DiceUI.GaiaAccountsStale", - gaia_accounts_stale); + + // Compute the default account. + SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile); + std::string default_account_id; + if (signin_manager->IsAuthenticated()) { + default_account_id = signin_manager->GetAuthenticatedAccountId(); + } else { + // Fetch accounts in the Gaia cookies. + GaiaCookieManagerService* cookie_manager_service = + GaiaCookieManagerServiceFactory::GetForProfile(profile); + std::vector<gaia::ListedAccount> cookie_accounts; + bool gaia_accounts_stale = !cookie_manager_service->ListAccounts( + &cookie_accounts, nullptr, "ProfileChooserView"); + UMA_HISTOGRAM_BOOLEAN("Profile.DiceUI.GaiaAccountsStale", + gaia_accounts_stale); + if (!cookie_accounts.empty()) + default_account_id = cookie_accounts[0].id; + } // Fetch account information for each id and make sure that the first account // in the list matches the first account in the Gaia cookies (if available). AccountTrackerService* account_tracker_service = AccountTrackerServiceFactory::GetForProfile(profile); - std::string gaia_default_account_id = - cookie_accounts.empty() ? "" : cookie_accounts[0].id; std::vector<AccountInfo> accounts; for (const std::string& account_id : account_ids) { DCHECK(!account_id.empty()); @@ -183,7 +188,7 @@ !signin_manager->IsAllowedUsername(account_info.email)) { continue; } - if (account_id == gaia_default_account_id) + if (account_id == default_account_id) accounts.insert(accounts.begin(), account_info); else accounts.push_back(account_info);
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 17dd6a3..c1791cf 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
@@ -441,6 +441,15 @@ ExpectUIShown(false); } +TEST_F(BlockTabUnderTest, SameSiteRedirect_NoBlocking) { + EXPECT_TRUE( + NavigateAndCommitWithoutGesture(GURL("https://sub1.blah.co.uk/"))); + SimulatePopup(); + EXPECT_TRUE( + NavigateAndCommitWithoutGesture(GURL("https://sub2.blah.co.uk/path"))); + ExpectUIShown(false); +} + TEST_F(BlockTabUnderTest, BrowserInitiatedNavigation_NoBlocking) { EXPECT_TRUE(NavigateAndCommitWithoutGesture(GURL("https://first.test/"))); SimulatePopup();
diff --git a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc index 72bc51d..5f8f42f 100644 --- a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc +++ b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.cc
@@ -24,10 +24,10 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/common/console_message_level.h" +#include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_recorder.h" #include "url/gurl.h" -#include "url/origin.h" #if defined(OS_ANDROID) #include "chrome/browser/ui/android/infobars/framebust_block_infobar.h" @@ -140,9 +140,10 @@ if (previous_main_frame_url.is_empty()) return false; - // Only cross origin navigations are considered tab-unders. - if (url::Origin::Create(previous_main_frame_url) - .IsSameOriginWith(url::Origin::Create(navigation_handle->GetURL()))) { + // Same-site navigations are exempt from tab-under protection. + if (net::registry_controlled_domains::SameDomainOrHost( + previous_main_frame_url, navigation_handle->GetURL(), + net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) { return false; }
diff --git a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h index 61403b6..749b72a9 100644 --- a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h +++ b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h
@@ -28,7 +28,7 @@ // 1. It is a navigation that is "suspicious" // a. It has no user gesture. // b. It is renderer-initiated. -// c. It is cross origin to the last committed URL in the tab. +// c. It is cross site to the last committed URL in the tab. // 2. The tab has opened a popup and hasn't received a user gesture since then. // This information is tracked by the PopupOpenerTabHelper. class TabUnderNavigationThrottle : public content::NavigationThrottle {
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc index 6afffb4..20842fa 100644 --- a/chrome/browser/ui/extensions/hosted_app_browser_controller.cc +++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.cc
@@ -24,7 +24,6 @@ #include "content/public/browser/web_contents.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/extension.h" -#include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "ui/gfx/favicon_size.h" #include "ui/gfx/image/image_skia.h" #include "url/gurl.h" @@ -200,10 +199,8 @@ return GetExtension()->short_name(); } -std::string HostedAppBrowserController::GetDomainAndRegistry() const { - return net::registry_controlled_domains::GetDomainAndRegistry( - AppLaunchInfo::GetLaunchWebURL(GetExtension()), - net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); +url::Origin HostedAppBrowserController::GetUrlOrigin() const { + return url::Origin::Create(AppLaunchInfo::GetLaunchWebURL(GetExtension())); } void HostedAppBrowserController::OnEngagementEvent(
diff --git a/chrome/browser/ui/extensions/hosted_app_browser_controller.h b/chrome/browser/ui/extensions/hosted_app_browser_controller.h index 3f973040..69c348e 100644 --- a/chrome/browser/ui/extensions/hosted_app_browser_controller.h +++ b/chrome/browser/ui/extensions/hosted_app_browser_controller.h
@@ -63,8 +63,8 @@ // Gets the short name of the app. std::string GetAppShortName() const; - // Gets the domain and registry of the app start url (e.g example.com.au). - std::string GetDomainAndRegistry() const; + // Gets the origin of the app start url (e.g www.example.com.au). + url::Origin GetUrlOrigin() const; // Gets the extension for this controller. const Extension* GetExtension() const;
diff --git a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc index df78a217..6f33e99 100644 --- a/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc +++ b/chrome/browser/ui/views/extensions/extension_installed_bubble_view.cc
@@ -26,6 +26,7 @@ #include "chrome/browser/ui/sync/bubble_sync_promo_delegate.h" #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h" #include "chrome/browser/ui/views/sync/bubble_sync_promo_view.h" +#include "chrome/browser/ui/views_mode_controller.h" #include "chrome/common/url_constants.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" @@ -78,6 +79,12 @@ Browser* browser) { BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); views::View* reference_view = nullptr; + +#if defined(OS_MACOSX) + if (views_mode_controller::IsViewsBrowserCocoa()) + return nullptr; +#endif + switch (controller->anchor_position()) { case ExtensionInstalledBubble::ANCHOR_ACTION: { BrowserActionsContainer* container =
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index 8d270c0..b8b40c8 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -12,6 +12,7 @@ #include "ash/frame/caption_buttons/frame_caption_button_container_view.h" #include "ash/frame/default_frame_header.h" #include "ash/frame/frame_border_hit_test.h" +#include "ash/frame/frame_header_origin_text.h" #include "ash/frame/frame_header_util.h" #include "ash/public/cpp/app_types.h" #include "ash/public/cpp/ash_switches.h" @@ -22,6 +23,10 @@ #include "ash/wm/overview/window_selector_controller.h" #include "ash/wm/window_util.h" #include "base/command_line.h" +#include "base/strings/utf_string_conversions.h" +#include "base/task_runner.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "base/time/time.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/profiles/profiles_state.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" @@ -67,6 +72,10 @@ constexpr SkColor kMdWebUIFrameColor = SkColorSetARGBMacro(0xff, 0x25, 0x4f, 0xae); +// How long to wait before starting the titlebar animation. +constexpr base::TimeDelta kTitlebarAnimationDelay = + base::TimeDelta::FromMilliseconds(750); + bool IsV1AppBackButtonEnabled() { return base::CommandLine::ForCurrentProcess()->HasSwitch( ash::switches::kAshEnableV1AppBackButton); @@ -93,6 +102,16 @@ } } +void SetRightSide(gfx::Rect* rect, int x) { + rect->set_x(x - rect->width()); + DCHECK_EQ(rect->right(), x); +} + +void AlignVerticalCenterWith(gfx::Rect* rect, const gfx::Rect& sibling) { + rect->set_y(sibling.y() + (sibling.height() - rect->height()) / 2); + DCHECK_EQ(rect->CenterPoint().y(), sibling.CenterPoint().y()); +} + } // namespace /////////////////////////////////////////////////////////////////////////////// @@ -106,7 +125,8 @@ back_button_(nullptr), window_icon_(nullptr), hosted_app_button_container_(nullptr), - observer_binding_(this) { + observer_binding_(this), + weak_factory_(this) { ash::wm::InstallResizeHandleWindowTargeterForWindow(frame->GetNativeWindow(), nullptr); ash::Shell::Get()->AddShellObserver(this); @@ -332,6 +352,9 @@ if (hosted_app_button_container_) hosted_app_button_container_->SetPaintAsActive(should_paint_as_active); + if (frame_header_origin_text_) + frame_header_origin_text_->SetPaintAsActive(should_paint_as_active); + if (browser_view()->IsToolbarVisible() && !browser_view()->toolbar()->GetPreferredSize().IsEmpty() && browser_view()->IsTabStripVisible()) { @@ -361,6 +384,21 @@ const int inset = (tab_strip_visible || immersive) ? 0 : GetTopInset(/*restored=*/false); frame()->GetNativeWindow()->SetProperty(aura::client::kTopViewInset, inset); + + if (frame_header_origin_text_) { + // Align the right side of the text with the left side of the caption + // buttons. + gfx::Size origin_text_preferred_size = + frame_header_origin_text_->GetPreferredSize(); + int origin_text_width = + std::min(width() - caption_button_container_->width(), + origin_text_preferred_size.width()); + gfx::Rect text_bounds(origin_text_width, + origin_text_preferred_size.height()); + SetRightSide(&text_bounds, caption_button_container_->x()); + AlignVerticalCenterWith(&text_bounds, caption_button_container_->bounds()); + frame_header_origin_text_->SetBoundsRect(text_bounds); + } } const char* BrowserNonClientFrameViewAsh::GetClassName() const { @@ -557,6 +595,8 @@ std::unique_ptr<ash::DefaultFrameHeader> default_frame_header = std::make_unique<ash::DefaultFrameHeader>(frame(), this, caption_button_container_); + + // TODO(alancutter): Move this branch into a new HostedAppFrameHeader class. if (extensions::HostedAppBrowserController::IsForExperimentalHostedAppBrowser( browser)) { // Hosted apps apply a theme color if specified by the extension. @@ -570,14 +610,33 @@ } // Add the container for extra hosted app buttons (e.g app menu button). - SkColor button_color = ash::FrameCaptionButton::GetButtonColor( + SkColor active_color = ash::FrameCaptionButton::GetButtonColor( default_frame_header->ShouldUseLightImages()); const float inactive_alpha_ratio = ash::FrameCaptionButton::GetInactiveButtonColorAlphaRatio(); + SkColor inactive_color = + SkColorSetA(active_color, 255 * inactive_alpha_ratio); hosted_app_button_container_ = new HostedAppButtonContainer( - browser_view(), button_color, - SkColorSetA(button_color, 255 * inactive_alpha_ratio)); + browser_view(), active_color, inactive_color); caption_button_container_->AddChildViewAt(hosted_app_button_container_, 0); + + // Add the origin text. + frame_header_origin_text_ = + std::make_unique<ash::FrameHeaderOriginText>( + base::UTF8ToUTF16( + browser->hosted_app_controller()->GetUrlOrigin().host()), + active_color, inactive_color, + default_frame_header->GetActiveFrameColor(), + default_frame_header->GetInactiveFrameColor()) + .release(); + AddChildView(frame_header_origin_text_); + + // Schedule the title bar animation. + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&BrowserNonClientFrameViewAsh::StartHostedAppAnimation, + weak_factory_.GetWeakPtr()), + kTitlebarAnimationDelay); } else if (!browser->is_app()) { // For non app (i.e. WebUI) windows (e.g. Settings) use MD frame color. default_frame_header->SetFrameColors(kMdWebUIFrameColor, @@ -592,3 +651,9 @@ return default_frame_header; } + +void BrowserNonClientFrameViewAsh::StartHostedAppAnimation() { + frame_header_origin_text_->StartSlideAnimation(); + hosted_app_button_container_->StartTitlebarAnimation( + frame_header_origin_text_->AnimationDuration()); +}
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h index 4282a506..682ad124 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -24,6 +24,7 @@ class FrameCaptionButton; class FrameCaptionButtonContainerView; class FrameHeader; +class FrameHeaderOriginText; } // Provides the BrowserNonClientFrameView for Chrome OS. @@ -128,6 +129,10 @@ // Creates the frame header for the browser window. std::unique_ptr<ash::FrameHeader> CreateFrameHeader(); + // Triggers the hosted app origin and icon animations, assumes the hosted app + // UI elements exist. + void StartHostedAppAnimation(); + // View which contains the window controls. ash::FrameCaptionButtonContainerView* caption_button_container_; @@ -143,6 +148,10 @@ // Owned by views hierarchy. HostedAppButtonContainer* hosted_app_button_container_; + // URL origin text for hosted app windows. + // Owned by views hierarchy. + ash::FrameHeaderOriginText* frame_header_origin_text_ = nullptr; + // Ash's mojom::SplitViewController. ash::mojom::SplitViewControllerPtr split_view_controller_; @@ -159,6 +168,8 @@ ash::mojom::SplitViewState split_view_state_ = ash::mojom::SplitViewState::NO_SNAP; + base::WeakPtrFactory<BrowserNonClientFrameViewAsh> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(BrowserNonClientFrameViewAsh); };
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index efccea6..fa38d0a 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -568,8 +568,8 @@ EXPECT_EQ(expected_active_icon_color, button_container->active_icon_color_); // Show a content setting icon. - auto& content_setting_views = - frame_view->hosted_app_button_container_->content_setting_views_; + auto& content_setting_views = frame_view->hosted_app_button_container_ + ->GetContentSettingViewsForTesting(); for (auto* v : content_setting_views) EXPECT_FALSE(v->visible());
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.cc b/chrome/browser/ui/views/frame/hosted_app_button_container.cc index 00e129d..e3d70cc 100644 --- a/chrome/browser/ui/views/frame/hosted_app_button_container.cc +++ b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
@@ -18,9 +18,13 @@ #include "chrome/grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/compositor/layer_animation_element.h" +#include "ui/compositor/layer_animation_sequence.h" +#include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/paint_vector_icon.h" +#include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" #include "ui/views/widget/native_widget_aura.h" @@ -29,6 +33,9 @@ // Padding around content setting icons. constexpr int kContentSettingIconInteriorPadding = 4; +constexpr base::TimeDelta kContentSettingsFadeInDuration = + base::TimeDelta::FromMilliseconds(500); + class HostedAppToolbarActionsBar : public ToolbarActionsBar { public: using ToolbarActionsBar::ToolbarActionsBar; @@ -45,6 +52,99 @@ } // namespace +class HostedAppButtonContainer::ContentSettingsContainer + : public views::View, + public ContentSettingImageView::Delegate { + public: + ContentSettingsContainer(BrowserView* browser_view, SkColor icon_color); + ~ContentSettingsContainer() override = default; + + // Updates the visibility of each content setting. + void RefreshContentSettingViews() { + for (auto* v : content_setting_views_) + v->Update(); + } + + // Sets the color of the content setting icons. + void SetIconColor(SkColor icon_color) { + for (auto* v : content_setting_views_) + v->SetIconColor(icon_color); + } + + void FadeIn() { + SetVisible(true); + DCHECK_EQ(layer()->opacity(), 0); + ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator()); + settings.SetTransitionDuration(kContentSettingsFadeInDuration); + layer()->SetOpacity(1); + } + + const std::vector<ContentSettingImageView*>& + GetContentSettingViewsForTesting() const { + return content_setting_views_; + } + + private: + // views::View: + void ChildVisibilityChanged(views::View* child) override { + PreferredSizeChanged(); + } + + // ContentSettingsImageView::Delegate: + content::WebContents* GetContentSettingWebContents() override { + return browser_view_->GetActiveWebContents(); + } + ContentSettingBubbleModelDelegate* GetContentSettingBubbleModelDelegate() + override { + return browser_view_->browser()->content_setting_bubble_model_delegate(); + } + void OnContentSettingImageBubbleShown( + ContentSettingImageModel::ImageType type) const override { + UMA_HISTOGRAM_ENUMERATION( + "HostedAppFrame.ContentSettings.ImagePressed", type, + ContentSettingImageModel::ImageType::NUM_IMAGE_TYPES); + } + + // Owned by the views hierarchy. + std::vector<ContentSettingImageView*> content_setting_views_; + + BrowserView* browser_view_; + + DISALLOW_COPY_AND_ASSIGN(ContentSettingsContainer); +}; + +const std::vector<ContentSettingImageView*>& +HostedAppButtonContainer::GetContentSettingViewsForTesting() const { + return content_settings_container_->GetContentSettingViewsForTesting(); +} + +HostedAppButtonContainer::ContentSettingsContainer::ContentSettingsContainer( + BrowserView* browser_view, + SkColor icon_color) + : browser_view_(browser_view) { + SetLayoutManager( + std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal)); + + SetVisible(false); + SetPaintToLayer(); + layer()->SetFillsBoundsOpaquely(false); + layer()->SetOpacity(0); + + std::vector<std::unique_ptr<ContentSettingImageModel>> models = + ContentSettingImageModel::GenerateContentSettingImageModels(); + for (auto& model : models) { + auto image_view = std::make_unique<ContentSettingImageView>( + std::move(model), this, + views::NativeWidgetAura::GetWindowTitleFontList()); + image_view->SetIconColor(icon_color); + image_view->set_next_element_interior_padding( + kContentSettingIconInteriorPadding); + image_view->disable_animation(); + content_setting_views_.push_back(image_view.get()); + AddChildView(image_view.release()); + } +} + HostedAppButtonContainer::AppMenuButton::AppMenuButton( BrowserView* browser_view) : views::MenuButton(base::string16(), this, false), @@ -81,6 +181,13 @@ menu_->RunMenu(this); } +void HostedAppButtonContainer::StartTitlebarAnimation( + base::TimeDelta origin_text_slide_duration) { + fade_in_content_setting_buttons_timer_.Start( + FROM_HERE, origin_text_slide_duration, content_settings_container_, + &ContentSettingsContainer::FadeIn); +} + HostedAppButtonContainer::HostedAppButtonContainer(BrowserView* browser_view, SkColor active_icon_color, SkColor inactive_icon_color) @@ -100,20 +207,10 @@ views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); SetLayoutManager(std::move(layout)); - std::vector<std::unique_ptr<ContentSettingImageModel>> models = - ContentSettingImageModel::GenerateContentSettingImageModels(); - for (auto& model : models) { - auto image_view = std::make_unique<ContentSettingImageView>( - std::move(model), this, - views::NativeWidgetAura::GetWindowTitleFontList()); - image_view->SetIconColor(active_icon_color); - image_view->set_next_element_interior_padding( - kContentSettingIconInteriorPadding); - image_view->SetVisible(false); - image_view->disable_animation(); - content_setting_views_.push_back(image_view.get()); - AddChildView(image_view.release()); - } + auto content_settings_container = std::make_unique<ContentSettingsContainer>( + browser_view, active_icon_color); + content_settings_container_ = content_settings_container.get(); + AddChildView(content_settings_container.release()); AddChildView(browser_actions_container_); @@ -126,37 +223,22 @@ HostedAppButtonContainer::~HostedAppButtonContainer() {} void HostedAppButtonContainer::RefreshContentSettingViews() { - for (auto* v : content_setting_views_) - v->Update(); + content_settings_container_->RefreshContentSettingViews(); } void HostedAppButtonContainer::SetPaintAsActive(bool active) { - for (auto* v : content_setting_views_) - v->SetIconColor(active ? active_icon_color_ : inactive_icon_color_); + content_settings_container_->SetIconColor(active ? active_icon_color_ + : inactive_icon_color_); app_menu_button_->SetIconColor(active ? active_icon_color_ : inactive_icon_color_); } -content::WebContents* HostedAppButtonContainer::GetContentSettingWebContents() { - return browser_view_->GetActiveWebContents(); -} - -ContentSettingBubbleModelDelegate* -HostedAppButtonContainer::GetContentSettingBubbleModelDelegate() { - return browser_view_->browser()->content_setting_bubble_model_delegate(); -} - -void HostedAppButtonContainer::OnContentSettingImageBubbleShown( - ContentSettingImageModel::ImageType type) const { - UMA_HISTOGRAM_ENUMERATION( - "HostedAppFrame.ContentSettings.ImagePressed", type, - ContentSettingImageModel::ImageType::NUM_IMAGE_TYPES); -} - void HostedAppButtonContainer::ChildPreferredSizeChanged(views::View* child) { - if (child != browser_actions_container_) + if (child != browser_actions_container_ && + child != content_settings_container_) { return; + } PreferredSizeChanged(); }
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.h b/chrome/browser/ui/views/frame/hosted_app_button_container.h index 4187f43..5e2015e 100644 --- a/chrome/browser/ui/views/frame/hosted_app_button_container.h +++ b/chrome/browser/ui/views/frame/hosted_app_button_container.h
@@ -21,7 +21,6 @@ // A container for hosted app buttons in the title bar. class HostedAppButtonContainer : public views::View, - public ContentSettingImageView::Delegate, public BrowserActionsContainer::Delegate, public BrowserViewButtonProvider { public: @@ -32,15 +31,24 @@ SkColor inactive_icon_color); ~HostedAppButtonContainer() override; - // Updates the visibility of each content setting view. + // Updates the visibility of each content setting. void RefreshContentSettingViews(); // Sets the container to paints its buttons the active/inactive color. void SetPaintAsActive(bool active); + // Animates the menu button and content setting icons. Intended to run in sync + // with a FrameHeaderOriginText slide animation. + void StartTitlebarAnimation(base::TimeDelta origin_text_slide_duration); + private: FRIEND_TEST_ALL_PREFIXES(HostedAppNonClientFrameViewAshTest, HostedAppFrame); + class ContentSettingsContainer; + + const std::vector<ContentSettingImageView*>& + GetContentSettingViewsForTesting() const; + // The 'app menu' button for the hosted app. class AppMenuButton : public views::MenuButton, public views::MenuButtonListener { @@ -71,12 +79,7 @@ DISALLOW_COPY_AND_ASSIGN(AppMenuButton); }; - // ContentSettingsImageView::Delegate: - content::WebContents* GetContentSettingWebContents() override; - ContentSettingBubbleModelDelegate* GetContentSettingBubbleModelDelegate() - override; - void OnContentSettingImageBubbleShown( - ContentSettingImageModel::ImageType type) const override; + void FadeInContentSettingButtons(); // views::View: void ChildPreferredSizeChanged(views::View* child) override; @@ -101,11 +104,15 @@ const SkColor active_icon_color_; const SkColor inactive_icon_color_; + base::OneShotTimer fade_in_content_setting_buttons_timer_; + // Owned by the views hierarchy. AppMenuButton* app_menu_button_; - std::vector<ContentSettingImageView*> content_setting_views_; + ContentSettingsContainer* content_settings_container_; BrowserActionsContainer* browser_actions_container_; + base::OneShotTimer opening_animation_timer_; + DISALLOW_COPY_AND_ASSIGN(HostedAppButtonContainer); };
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index 01d7b65..4177b12 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -569,18 +569,18 @@ } }; + if (star_view_) + add_trailing_decoration(star_view_); + add_trailing_decoration(zoom_view_); + add_trailing_decoration(find_bar_icon_); #if defined(OS_CHROMEOS) if (intent_picker_view_) add_trailing_decoration(intent_picker_view_); #endif - if (star_view_) - add_trailing_decoration(star_view_); - add_trailing_decoration(find_bar_icon_); add_trailing_decoration(translate_icon_view_); if (save_credit_card_icon_view_) add_trailing_decoration(save_credit_card_icon_view_); add_trailing_decoration(manage_passwords_icon_view_); - add_trailing_decoration(zoom_view_); for (ContentSettingViews::const_reverse_iterator i( content_setting_views_.rbegin()); i != content_setting_views_.rend(); ++i) {
diff --git a/chrome/browser/ui/views/profiles/dice_accounts_menu.cc b/chrome/browser/ui/views/profiles/dice_accounts_menu.cc index 6e59c69..5ad7f9e 100644 --- a/chrome/browser/ui/views/profiles/dice_accounts_menu.cc +++ b/chrome/browser/ui/views/profiles/dice_accounts_menu.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/views/profiles/dice_accounts_menu.h" #include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" #include "chrome/browser/profiles/profile_avatar_icon_util.h" #include "chrome/grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" @@ -92,13 +93,25 @@ // Calculate custom anchor bounds to position the menu. // The menu is aligned along the right edge (left edge in RTL mode) of the // anchor, slightly shifted inside by |kAnchorInset| and overlapping - // |anchor_view| on the bottom by |kAnchorInset|. |anchor_bounds|' width is - // set to 0 so that the menu only is as wide as it needs to be. + // |anchor_view| on the bottom by |kAnchorInset|. |anchor_bounds| is collapsed + // so the menu only takes the width it needs. gfx::Rect anchor_bounds = anchor_view->GetBoundsInScreen(); - anchor_bounds.Inset( - base::i18n::IsRTL() ? kAnchorInset : anchor_bounds.width() - kAnchorInset, - kAnchorInset, 0, kAnchorInset); - anchor_bounds.set_width(0); + anchor_bounds.Inset(kAnchorInset, kAnchorInset); +#if defined(OS_MACOSX) + // On Mac, menus align to the left of the anchor, so collapse the right side + // of the rect. + bool collapse_right = true; +#else + bool collapse_right = false; +#endif + if (base::i18n::IsRTL()) + collapse_right = !collapse_right; + + if (collapse_right) + anchor_bounds.Inset(0, 0, anchor_bounds.width(), 0); + else + anchor_bounds.Inset(anchor_bounds.width(), 0, 0, 0); + runner_->RunMenuAt(anchor_view->GetWidget(), nullptr, anchor_bounds, views::MENU_ANCHOR_TOPRIGHT, ui::MENU_SOURCE_MOUSE); }
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.cc b/chrome/browser/ui/views/tabs/new_tab_button.cc index 7e8a3811..b368fb5 100644 --- a/chrome/browser/ui/views/tabs/new_tab_button.cc +++ b/chrome/browser/ui/views/tabs/new_tab_button.cc
@@ -14,7 +14,7 @@ #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "components/feature_engagement/buildflags.h" #include "third_party/skia/include/core/SkColorFilter.h" -#include "third_party/skia/include/effects/SkBlurMaskFilter.h" +#include "third_party/skia/include/core/SkMaskFilter.h" #include "third_party/skia/include/effects/SkLayerDrawLooper.h" #include "third_party/skia/include/pathops/SkPathOps.h" #include "ui/base/default_theme_provider.h" @@ -55,8 +55,7 @@ layer_info.fColorMode = SkBlendMode::kDst; layer_info.fOffset.set(0, 1); SkPaint* layer_paint = looper_builder.addLayer(layer_info); - layer_paint->setMaskFilter(SkBlurMaskFilter::Make( - kNormal_SkBlurStyle, 0.5, SkBlurMaskFilter::kHighQuality_BlurFlag)); + layer_paint->setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 0.5)); layer_paint->setColorFilter( SkColorFilter::MakeModeFilter(color, SkBlendMode::kSrcIn)); return looper_builder.detach();
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 6c330cd..e0923404 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -38,7 +38,6 @@ #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" #include "third_party/skia/include/core/SkColorFilter.h" -#include "third_party/skia/include/effects/SkBlurMaskFilter.h" #include "third_party/skia/include/effects/SkLayerDrawLooper.h" #include "third_party/skia/include/pathops/SkPathOps.h" #include "ui/accessibility/ax_node_data.h"
diff --git a/chrome/browser/ui/webui/policy_tool_ui.cc b/chrome/browser/ui/webui/policy_tool_ui.cc index 4152ba140..05974ca 100644 --- a/chrome/browser/ui/webui/policy_tool_ui.cc +++ b/chrome/browser/ui/webui/policy_tool_ui.cc
@@ -29,10 +29,14 @@ source->AddLocalizedString("hideExpandedValue", IDS_POLICY_HIDE_EXPANDED_VALUE); source->AddLocalizedString("loadSession", IDS_POLICY_TOOL_LOAD_SESSION); + source->AddLocalizedString("removeSession", IDS_POLICY_TOOL_REMOVE_SESSION); + source->AddLocalizedString("renameSession", IDS_POLICY_TOOL_RENAME_SESSION); source->AddLocalizedString("sessionNamePlaceholder", IDS_POLICY_TOOL_SESSION_NAME_PLACEHOLDER); source->AddLocalizedString("filterPlaceholder", IDS_POLICY_FILTER_PLACEHOLDER); + source->AddLocalizedString("cancelRename", IDS_POLICY_TOOL_CANCEL_RENAME); + source->AddLocalizedString("confirmRename", IDS_POLICY_TOOL_CONFIRM_RENAME); source->AddLocalizedString("edit", IDS_POLICY_TOOL_EDIT); source->AddLocalizedString("save", IDS_POLICY_TOOL_SAVE); source->AddLocalizedString("errorSavingDisabled", @@ -42,6 +46,12 @@ source->AddLocalizedString("errorFileCorrupted", IDS_POLICY_TOOL_CORRUPTED_FILE); source->AddLocalizedString("enableEditing", IDS_POLICY_TOOL_ENABLE_EDITING); + source->AddLocalizedString("errorRenameFailed", + IDS_POLICY_TOOL_RENAME_FAILED); + source->AddLocalizedString("errorSessionExist", + IDS_POLICY_TOOL_SESSION_EXIST); + source->AddLocalizedString("errorSessionNotExist", + IDS_POLICY_TOOL_SESSION_NOT_EXIST); source->AddLocalizedString("errorDeleteFailed", IDS_POLICY_TOOL_DELETE_FAILED); // Overwrite the title value added by PolicyUIHandler.
diff --git a/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc b/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc index 6700b11..b7ee406b 100644 --- a/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc +++ b/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
@@ -6,6 +6,7 @@ #include "base/json/json_writer.h" #include "base/macros.h" #include "base/path_service.h" +#include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" #include "base/threading/thread_restrictions.h" @@ -40,10 +41,13 @@ void LoadSession(const std::string& session_name); void DeleteSession(const std::string& session_name); + void RenameSession(const std::string& session_name, + const std::string& new_session_name); std::unique_ptr<base::DictionaryValue> ExtractPolicyValues(bool need_status); bool IsInvalidSessionNameErrorMessageDisplayed(); + bool IsSessionRenameErrorMessageDisplayed(); std::unique_ptr<base::ListValue> ExtractSessionsList(); @@ -114,6 +118,18 @@ content::RunAllTasksUntilIdle(); } +void PolicyToolUITest::RenameSession(const std::string& session_name, + const std::string& new_session_name) { + const std::string javascript = + base::StrCat({"$('session-list').value = '", session_name, "';", + "$('rename-session-button').click();", + "$('new-session-name-field').value = '", new_session_name, + "';", "$('confirm-rename-button').click();"}); + EXPECT_TRUE(content::ExecuteScript( + browser()->tab_strip_model()->GetActiveWebContents(), javascript)); + content::RunAllTasksUntilIdle(); +} + std::unique_ptr<base::DictionaryValue> PolicyToolUITest::ExtractPolicyValues( bool need_status) { std::string javascript = @@ -170,6 +186,16 @@ return result; } +bool PolicyToolUITest::IsSessionRenameErrorMessageDisplayed() { + constexpr char kJavascript[] = + "domAutomationController.send($('session-rename-error').hidden == false)"; + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + bool result = false; + EXPECT_TRUE(ExecuteScriptAndExtractBool(contents, kJavascript, &result)); + return result; +} + void PolicyToolUITest::CreateMultipleSessionFiles(int count) { base::ScopedAllowBlockingForTesting allow_blocking; EXPECT_TRUE(base::CreateDirectory(GetSessionsDir())); @@ -429,3 +455,54 @@ expected.GetList().erase(expected.GetList().begin()); EXPECT_EQ(expected, *ExtractSessionsList()); } + +IN_PROC_BROWSER_TEST_F(PolicyToolUITest, RenameSession) { + CreateMultipleSessionFiles(3); + ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool")); + EXPECT_EQ("2", ExtractSinglePolicyValue("SessionId")); + + // Check that a non-current session is renamed correctly. + RenameSession("0", "4"); + EXPECT_FALSE(IsSessionRenameErrorMessageDisplayed()); + base::ListValue expected; + expected.GetList().push_back(base::Value("2")); + expected.GetList().push_back(base::Value("1")); + expected.GetList().push_back(base::Value("4")); + EXPECT_EQ(expected, *ExtractSessionsList()); + + // Check that the current session can be renamed properly. + RenameSession("2", "5"); + EXPECT_FALSE(IsSessionRenameErrorMessageDisplayed()); + expected.GetList()[0] = base::Value("5"); + EXPECT_EQ(expected, *ExtractSessionsList()); +} + +IN_PROC_BROWSER_TEST_F(PolicyToolUITest, RenameSessionWithExistingSessionName) { + CreateMultipleSessionFiles(3); + ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool")); + EXPECT_EQ("2", ExtractSinglePolicyValue("SessionId")); + + // Check that a session can not be renamed with a name of another existing + // session. + RenameSession("2", "1"); + EXPECT_TRUE(IsSessionRenameErrorMessageDisplayed()); + base::ListValue expected; + expected.GetList().push_back(base::Value("2")); + expected.GetList().push_back(base::Value("1")); + expected.GetList().push_back(base::Value("0")); + EXPECT_EQ(expected, *ExtractSessionsList()); +} + +IN_PROC_BROWSER_TEST_F(PolicyToolUITest, RenameSessionInvalidName) { + CreateMultipleSessionFiles(3); + ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool")); + EXPECT_EQ("2", ExtractSinglePolicyValue("SessionId")); + + RenameSession("2", "../"); + EXPECT_TRUE(IsSessionRenameErrorMessageDisplayed()); + base::ListValue expected; + expected.GetList().push_back(base::Value("2")); + expected.GetList().push_back(base::Value("1")); + expected.GetList().push_back(base::Value("0")); + EXPECT_EQ(expected, *ExtractSessionsList()); +}
diff --git a/chrome/browser/ui/webui/policy_tool_ui_handler.cc b/chrome/browser/ui/webui/policy_tool_ui_handler.cc index fd437004..03517416 100644 --- a/chrome/browser/ui/webui/policy_tool_ui_handler.cc +++ b/chrome/browser/ui/webui/policy_tool_ui_handler.cc
@@ -12,6 +12,8 @@ #include "base/task_scheduler/post_task.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" +#include "components/strings/grit/components_strings.h" +#include "ui/base/l10n/l10n_util.h" // static const base::FilePath::CharType PolicyToolUIHandler::kPolicyToolSessionsDir[] = @@ -37,20 +39,29 @@ Profile::FromWebUI(web_ui())->GetPath().Append(kPolicyToolSessionsDir); web_ui()->RegisterMessageCallback( - "initialized", base::Bind(&PolicyToolUIHandler::HandleInitializedAdmin, - base::Unretained(this))); + "initialized", + base::BindRepeating(&PolicyToolUIHandler::HandleInitializedAdmin, + base::Unretained(this))); web_ui()->RegisterMessageCallback( - "loadSession", base::Bind(&PolicyToolUIHandler::HandleLoadSession, - base::Unretained(this))); + "loadSession", + base::BindRepeating(&PolicyToolUIHandler::HandleLoadSession, + base::Unretained(this))); web_ui()->RegisterMessageCallback( - "updateSession", base::Bind(&PolicyToolUIHandler::HandleUpdateSession, - base::Unretained(this))); + "renameSession", + base::BindRepeating(&PolicyToolUIHandler::HandleRenameSession, + base::Unretained(this))); web_ui()->RegisterMessageCallback( - "resetSession", base::Bind(&PolicyToolUIHandler::HandleResetSession, - base::Unretained(this))); + "updateSession", + base::BindRepeating(&PolicyToolUIHandler::HandleUpdateSession, + base::Unretained(this))); web_ui()->RegisterMessageCallback( - "deleteSession", base::Bind(&PolicyToolUIHandler::HandleDeleteSession, - base::Unretained(this))); + "resetSession", + base::BindRepeating(&PolicyToolUIHandler::HandleResetSession, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "deleteSession", + base::BindRepeating(&PolicyToolUIHandler::HandleDeleteSession, + base::Unretained(this))); } void PolicyToolUIHandler::OnJavascriptDisallowed() { @@ -165,6 +176,8 @@ // TODO(urusant): convert the policy values so that the types are // consistent with actual policy types. CallJavascriptFunction("policy.Page.setPolicyValues", *value); + CallJavascriptFunction("policy.Page.setSessionTitle", + base::Value(session_name_)); base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, base::BindOnce(&PolicyToolUIHandler::GetSessionsList, @@ -215,6 +228,79 @@ ImportFile(); } +PolicyToolUIHandler::SessionErrors PolicyToolUIHandler::DoRenameSession( + const base::FilePath::StringType& old_session_name, + const base::FilePath::StringType& new_session_name) { + const base::FilePath old_session_path = GetSessionPath(old_session_name); + const base::FilePath new_session_path = GetSessionPath(new_session_name); + + // Check if the session files exist. If |old_session_name| doesn't exist, it + // means that is not a valid session. If |new_session_name| exists, it means + // that we can't do the rename because that will cause a file overwrite. + if (!PathExists(old_session_path)) + return SessionErrors::kSessionNameNotExist; + if (PathExists(new_session_path)) + return SessionErrors::kSessionNameExist; + if (!base::Move(old_session_path, new_session_path)) + return SessionErrors::kRenamedSessionError; + return SessionErrors::kNone; +} + +void PolicyToolUIHandler::OnSessionRenamed( + PolicyToolUIHandler::SessionErrors result) { + if (result == SessionErrors::kNone) { + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, + base::BindOnce(&PolicyToolUIHandler::GetSessionsList, + base::Unretained(this)), + base::BindOnce(&PolicyToolUIHandler::OnSessionsListReceived, + callback_weak_ptr_factory_.GetWeakPtr())); + CallJavascriptFunction("policy.Page.closeRenameSessionDialog"); + return; + } + int error_message_id; + if (result == SessionErrors::kSessionNameNotExist) { + error_message_id = IDS_POLICY_TOOL_SESSION_NOT_EXIST; + } else if (result == SessionErrors::kSessionNameExist) { + error_message_id = IDS_POLICY_TOOL_SESSION_EXIST; + } else { + error_message_id = IDS_POLICY_TOOL_RENAME_FAILED; + } + + CallJavascriptFunction( + "policy.Page.showRenameSessionError", + base::Value(l10n_util::GetStringUTF16(error_message_id))); +} + +void PolicyToolUIHandler::HandleRenameSession(const base::ListValue* args) { + DCHECK_EQ(2U, args->GetSize()); + base::FilePath::StringType old_session_name, new_session_name; + old_session_name = + base::FilePath::FromUTF8Unsafe(args->GetList()[0].GetString()).value(); + new_session_name = + base::FilePath::FromUTF8Unsafe(args->GetList()[1].GetString()).value(); + + if (!IsValidSessionName(new_session_name) || + !IsValidSessionName(old_session_name)) { + CallJavascriptFunction("policy.Page.showRenameSessionError", + base::Value(l10n_util::GetStringUTF16( + IDS_POLICY_TOOL_INVALID_SESSION_NAME))); + return; + } + + // This is important in case the user renames the current active session. + // If we don't clear the current session name, after the rename, a new file + // will be created with the old name and with an empty dictionary in it. + session_name_.clear(); + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING}, + base::BindOnce(&PolicyToolUIHandler::DoRenameSession, + base::Unretained(this), old_session_name, + new_session_name), + base::BindOnce(&PolicyToolUIHandler::OnSessionRenamed, + callback_weak_ptr_factory_.GetWeakPtr())); +} + bool PolicyToolUIHandler::DoUpdateSession(const std::string& contents) { // Sanity check that contents is not too big. Otherwise, passing it to // WriteFile will be int overflow.
diff --git a/chrome/browser/ui/webui/policy_tool_ui_handler.h b/chrome/browser/ui/webui/policy_tool_ui_handler.h index c520df0a..8ea81955 100644 --- a/chrome/browser/ui/webui/policy_tool_ui_handler.h +++ b/chrome/browser/ui/webui/policy_tool_ui_handler.h
@@ -20,6 +20,14 @@ private: friend class PolicyToolUITest; + enum class SessionErrors { + kNone = 0, + kInvalidSessionName, + kSessionNameExist, + kSessionNameNotExist, + kRenamedSessionError, + }; + static const base::FilePath::CharType kPolicyToolSessionsDir[]; static const base::FilePath::CharType kPolicyToolDefaultSessionName[]; static const base::FilePath::CharType kPolicyToolSessionExtension[]; @@ -28,9 +36,16 @@ void ImportFile(); void HandleInitializedAdmin(const base::ListValue* args); + void HandleLoadSession(const base::ListValue* args); + + // Rename a session if the new session name doesn't exist. + void HandleRenameSession(const base::ListValue* args); + void HandleUpdateSession(const base::ListValue* args); + void HandleResetSession(const base::ListValue* args); + void HandleDeleteSession(const base::ListValue* args); void OnSessionDeleted(bool is_successful); @@ -38,7 +53,14 @@ std::string ReadOrCreateFileCallback(); void OnFileRead(const std::string& contents); + SessionErrors DoRenameSession( + const base::FilePath::StringType& old_session_name, + const base::FilePath::StringType& new_session_name); + + void OnSessionRenamed(SessionErrors result); + bool DoUpdateSession(const std::string& contents); + void OnSessionUpdated(bool is_successful); bool IsValidSessionName(const base::FilePath::StringType& name) const;
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc index 707c0a05..c470c3b 100644 --- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc +++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
@@ -65,14 +65,21 @@ DCHECK(delegate_); DCHECK(signin::IsDicePrepareMigrationEnabled()); DCHECK(profile_); - DCHECK(!account_info_.gaia.empty()); - DCHECK(!account_info_.email.empty()); // Should not start syncing if the profile is already authenticated DCHECK(!signin_manager_->IsAuthenticated()); // Force sign-in uses the modal sign-in flow. DCHECK(!signin_util::IsForceSigninEnabled()); + if (account_info_.gaia.empty() || account_info_.email.empty()) { + LOG(ERROR) << "Cannot turn Sync On for invalid account."; + base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); + return; + } + + DCHECK(!account_info_.gaia.empty()); + DCHECK(!account_info_.email.empty()); + if (HasCanOfferSigninError()) { // Do not self-destruct synchronously in the constructor. base::SequencedTaskRunnerHandle::Get()->PostTask(
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h index 6641331..338f75e 100644 --- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h +++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h
@@ -113,6 +113,8 @@ void SyncStartupFailed() override; private: + friend class base::DeleteHelper<DiceTurnSyncOnHelper>; + enum class ProfileMode { // Attempts to sign the user in |profile_|. Note that if the account to be // signed in is a managed account, then a profile confirmation dialog is
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc index ec518a4..127f4ef 100644 --- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc +++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
@@ -235,6 +235,8 @@ token_service_->UpdateCredentials(account_id_, "enterprise_refresh_token"); } + void UseInvalidAccount() { account_id_ = "invalid_account"; } + void SetExpectationsForSyncStartupCompleted() { browser_sync::ProfileSyncServiceMock* sync_service_mock = GetProfileSyncServiceMock(); @@ -431,6 +433,15 @@ test_fixture_->OnShowSigninPageInNewProfile(new_profile, username); } +// Check that the invalid account is supported. +TEST_F(DiceTurnSyncOnHelperTest, InvalidAccount) { + UseInvalidAccount(); + CreateDiceTurnOnSyncHelper( + DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT); + base::RunLoop().RunUntilIdle(); + CheckDelegateCalls(); +} + // Tests that the login error is displayed and that the account is kept. TEST_F(DiceTurnSyncOnHelperTest, CanOfferSigninErrorKeepAccount) { // Set expectations.
diff --git a/chrome/browser/update_client/chrome_update_query_params_delegate.cc b/chrome/browser/update_client/chrome_update_query_params_delegate.cc index 0475535..1712095b 100644 --- a/chrome/browser/update_client/chrome_update_query_params_delegate.cc +++ b/chrome/browser/update_client/chrome_update_query_params_delegate.cc
@@ -13,7 +13,7 @@ namespace { base::LazyInstance<ChromeUpdateQueryParamsDelegate>::DestructorAtExit - g_delegate = LAZY_INSTANCE_INITIALIZER; + g_chrome_update_query_params_delegate = LAZY_INSTANCE_INITIALIZER; } // namespace @@ -26,7 +26,7 @@ // static ChromeUpdateQueryParamsDelegate* ChromeUpdateQueryParamsDelegate::GetInstance() { - return g_delegate.Pointer(); + return g_chrome_update_query_params_delegate.Pointer(); } std::string ChromeUpdateQueryParamsDelegate::GetExtraParams() {
diff --git a/chrome/browser/win/automation_controller.cc b/chrome/browser/win/automation_controller.cc index 5797e85..80782657 100644 --- a/chrome/browser/win/automation_controller.cc +++ b/chrome/browser/win/automation_controller.cc
@@ -16,10 +16,10 @@ #include "base/bind.h" #include "base/logging.h" -#include "base/single_thread_task_runner.h" +#include "base/sequence_checker.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" -#include "base/threading/thread_checker.h" +#include "base/task_scheduler/post_task.h" #include "base/win/scoped_variant.h" #include "chrome/browser/win/ui_automation_util.h" #include "ui/base/win/atl_module.h" @@ -96,15 +96,16 @@ } // namespace -// This class lives on the automation thread and is responsible for initializing -// the UIAutomation library and installing the event observers. +// This class lives in the automation sequence and is responsible for +// initializing the UIAutomation library and installing the event observers. class AutomationController::Context { public: - // Returns a new instance ready for initialization and use on another thread. + // Returns a new instance ready for initialization and use in another + // sequence. static base::WeakPtr<Context> Create(); // Deletes the instance. - void DeleteOnAutomationThread(); + void DeleteInAutomationSequence(); // Initializes the context, invoking the delegate's OnInitialized() method // when done. On success, the delegate's other On*() methods will be invoked @@ -116,7 +117,7 @@ class EventHandler; // The one and only method that may be called from outside of the automation - // thread. + // sequence. Context(); ~Context(); @@ -136,7 +137,7 @@ // Pointer to the delegate. Passed to event handlers. scoped_refptr<RefCountedDelegate> ref_counted_delegate_; - THREAD_CHECKER(thread_checker_); + SEQUENCE_CHECKER(sequence_checker_); // The automation client. Microsoft::WRL::ComPtr<IUIAutomation> automation_; @@ -250,15 +251,15 @@ return context->weak_ptr_factory_.GetWeakPtr(); } -void AutomationController::Context::DeleteOnAutomationThread() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); +void AutomationController::Context::DeleteInAutomationSequence() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); delete this; } void AutomationController::Context::Initialize( std::unique_ptr<Delegate> delegate) { - // This and all other methods must be called on the automation thread. - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + // This and all other methods must be called in the automation sequence. + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ref_counted_delegate_ = base::MakeRefCounted<RefCountedDelegate>(std::move(delegate)); @@ -279,11 +280,11 @@ } AutomationController::Context::Context() : weak_ptr_factory_(this) { - DETACH_FROM_THREAD(thread_checker_); + DETACH_FROM_SEQUENCE(sequence_checker_); } AutomationController::Context::~Context() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (event_handler_) { event_handler_.Reset(); automation_->RemoveAllEventHandlers(); @@ -292,7 +293,7 @@ Microsoft::WRL::ComPtr<IUnknown> AutomationController::Context::GetEventHandler() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!event_handler_) { ATL::CComObject<EventHandler>* obj = nullptr; HRESULT result = ATL::CComObject<EventHandler>::CreateInstance(&obj); @@ -306,7 +307,7 @@ Microsoft::WRL::ComPtr<IUIAutomationEventHandler> AutomationController::Context::GetAutomationEventHandler() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); Microsoft::WRL::ComPtr<IUIAutomationEventHandler> handler; GetEventHandler().CopyTo(handler.GetAddressOf()); return handler; @@ -314,14 +315,14 @@ Microsoft::WRL::ComPtr<IUIAutomationFocusChangedEventHandler> AutomationController::Context::GetFocusChangedEventHandler() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); Microsoft::WRL::ComPtr<IUIAutomationFocusChangedEventHandler> handler; GetEventHandler().CopyTo(handler.GetAddressOf()); return handler; } HRESULT AutomationController::Context::InstallObservers() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(automation_); // Create a cache request so that elements received by way of events contain @@ -354,25 +355,28 @@ // AutomationController -------------------------------------------------------- -AutomationController::AutomationController(std::unique_ptr<Delegate> delegate) - : automation_thread_("AutomationControllerThread") { +AutomationController::AutomationController(std::unique_ptr<Delegate> delegate) { ui::win::CreateATLModuleIfNeeded(); - // Start the automation thread and initialize the automation client on it. + + // Create the task runner on which the automation client lives. + automation_task_runner_ = base::CreateSequencedTaskRunnerWithTraits( + {base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}); + + // Initialize the context on the automation task runner. context_ = Context::Create(); - automation_thread_.init_com_with_mta(true); - automation_thread_.Start(); - automation_thread_.task_runner()->PostTask( + automation_task_runner_->PostTask( FROM_HERE, base::BindOnce(&AutomationController::Context::Initialize, context_, std::move(delegate))); } AutomationController::~AutomationController() { // context_ is still valid when the caller destroys the instance before the - // callback(s) have fired. In this case, delete the context on the automation - // thread before joining with it. DeleteSoon is not used because the monitor - // has only a WeakPtr to the context that is bound to the automation thread. - automation_thread_.task_runner()->PostTask( + // callback(s) have fired. In this case, delete the context in the automation + // sequence before joining with it. DeleteSoon is not used because the monitor + // has only a WeakPtr to the context that is bound to the automation sequence. + automation_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&AutomationController::Context::DeleteOnAutomationThread, + base::BindOnce(&AutomationController::Context::DeleteInAutomationSequence, context_)); }
diff --git a/chrome/browser/win/automation_controller.h b/chrome/browser/win/automation_controller.h index d3c37ca..d9c16596 100644 --- a/chrome/browser/win/automation_controller.h +++ b/chrome/browser/win/automation_controller.h
@@ -13,8 +13,9 @@ #include <memory> #include "base/macros.h" +#include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" -#include "base/threading/thread.h" +#include "base/sequenced_task_runner.h" // This is a helper class to facilitate the usage of the UI Automation API in // the Chrome codebase. It takes care of initializing the Automation context and @@ -27,11 +28,11 @@ // outside of the Task Scheduler's control. class AutomationController { public: - // The delegate is passed to the automation thread and the event handlers, + // The delegate is passed to the automation sequence and the event handlers, // which runs in the context of a MTA. // // The call order is as follows: - // - OnInitialized() is invoked on the automation thread. + // - OnInitialized() is invoked in the automation sequence. // If initialization succeeds: // - ConfigureCacheRequest() is invoked once per type of event. // - OnAutomationEvent() and OnFocusChangedEvent() are invoked as events @@ -52,20 +53,20 @@ // Used to configure the event handlers so that the event sender element has // the required properties cached. - // Runs on the context thread. + // Runs in the automation sequence. virtual void ConfigureCacheRequest( IUIAutomationCacheRequest* cache_request) const = 0; // Invoked when an automation event happens. - // This can be invoked on any thread in the automation MTA and so |this| - // should be accessed carefully. + // This can be invoked on any MTA thread in the process and so |this| should + // be accessed carefully. virtual void OnAutomationEvent(IUIAutomation* automation, IUIAutomationElement* sender, EVENTID event_id) const = 0; // Invoked when a focus changed event happens. - // This can be invoked on any thread in the automation MTA and so |this| - // should be accessed carefully. + // This can be invoked on any MTA thread in the process and so |this| should + // be accessed carefully. virtual void OnFocusChangedEvent(IUIAutomation* automation, IUIAutomationElement* sender) const = 0; }; @@ -76,10 +77,10 @@ private: class Context; - // A thread in the COM MTA in which automation calls are made. - base::Thread automation_thread_; + // The sequence in which automation calls are made. + scoped_refptr<base::SequencedTaskRunner> automation_task_runner_; - // A pointer to the context object that lives on the automation thread. + // A pointer to the context object that lives in the automation sequence. base::WeakPtr<Context> context_; DISALLOW_COPY_AND_ASSIGN(AutomationController);
diff --git a/chrome/services/file_util/BUILD.gn b/chrome/services/file_util/BUILD.gn index bced96a..4f117a49 100644 --- a/chrome/services/file_util/BUILD.gn +++ b/chrome/services/file_util/BUILD.gn
@@ -28,7 +28,7 @@ "zip_file_creator.h", ] - deps += [ "//components/filesystem/public/interfaces" ] + deps += [ "//components/services/filesystem/public/interfaces" ] } if (safe_browsing_mode == 1) {
diff --git a/chrome/services/file_util/DEPS b/chrome/services/file_util/DEPS index bde581c..e480585 100644 --- a/chrome/services/file_util/DEPS +++ b/chrome/services/file_util/DEPS
@@ -1,5 +1,5 @@ include_rules = [ - "+components/filesystem", + "+components/services/filesystem", "+chrome/utility/safe_browsing", "+third_party/zlib/google", ]
diff --git a/chrome/services/file_util/public/cpp/zip_file_creator.cc b/chrome/services/file_util/public/cpp/zip_file_creator.cc index ca8202b..754ff57 100644 --- a/chrome/services/file_util/public/cpp/zip_file_creator.cc +++ b/chrome/services/file_util/public/cpp/zip_file_creator.cc
@@ -10,8 +10,8 @@ #include "base/callback_helpers.h" #include "base/task_scheduler/post_task.h" #include "chrome/services/file_util/public/mojom/constants.mojom.h" -#include "components/filesystem/directory_impl.h" -#include "components/filesystem/lock_table.h" +#include "components/services/filesystem/directory_impl.h" +#include "components/services/filesystem/lock_table.h" #include "content/public/browser/browser_thread.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/service_manager/public/cpp/connector.h"
diff --git a/chrome/services/file_util/public/mojom/BUILD.gn b/chrome/services/file_util/public/mojom/BUILD.gn index 28d78b2..0ed19564 100644 --- a/chrome/services/file_util/public/mojom/BUILD.gn +++ b/chrome/services/file_util/public/mojom/BUILD.gn
@@ -20,6 +20,6 @@ if (is_chromeos) { sources += [ "zip_file_creator.mojom" ] - public_deps += [ "//components/filesystem/public/interfaces" ] + public_deps += [ "//components/services/filesystem/public/interfaces" ] } }
diff --git a/chrome/services/file_util/public/mojom/zip_file_creator.mojom b/chrome/services/file_util/public/mojom/zip_file_creator.mojom index 0bf85f9d..fae0034 100644 --- a/chrome/services/file_util/public/mojom/zip_file_creator.mojom +++ b/chrome/services/file_util/public/mojom/zip_file_creator.mojom
@@ -7,7 +7,7 @@ module chrome.mojom; -import "components/filesystem/public/interfaces/directory.mojom"; +import "components/services/filesystem/public/interfaces/directory.mojom"; import "mojo/common/file.mojom"; import "mojo/common/file_path.mojom";
diff --git a/chrome/services/file_util/zip_file_creator.cc b/chrome/services/file_util/zip_file_creator.cc index f026e1f..81933d5 100644 --- a/chrome/services/file_util/zip_file_creator.cc +++ b/chrome/services/file_util/zip_file_creator.cc
@@ -9,7 +9,7 @@ #include "base/files/file.h" #include "base/files/file_path.h" -#include "components/filesystem/public/interfaces/types.mojom-shared.h" +#include "components/services/filesystem/public/interfaces/types.mojom-shared.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "third_party/zlib/google/zip.h"
diff --git a/chrome/services/file_util/zip_file_creator.h b/chrome/services/file_util/zip_file_creator.h index febd8dcb3..f772f668 100644 --- a/chrome/services/file_util/zip_file_creator.h +++ b/chrome/services/file_util/zip_file_creator.h
@@ -8,7 +8,7 @@ #include <vector> #include "chrome/services/file_util/public/mojom/zip_file_creator.mojom.h" -#include "components/filesystem/public/interfaces/directory.mojom.h" +#include "components/services/filesystem/public/interfaces/directory.mojom.h" #include "services/service_manager/public/cpp/service_context_ref.h" namespace base {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index fbd11cd9..770e6330 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1224,6 +1224,7 @@ "../browser/extensions/content_script_apitest.cc", "../browser/extensions/content_security_policy_apitest.cc", "../browser/extensions/content_verifier_browsertest.cc", + "../browser/extensions/content_verifier_hash_fetch_behavior_browsertest.cc", "../browser/extensions/cross_origin_xhr_apitest.cc", "../browser/extensions/crx_installer_browsertest.cc", "../browser/extensions/docs/examples/apps/calculator_browsertest.cc", @@ -1961,7 +1962,7 @@ if (enable_library_cdms) { # Runtime dependencies. data_deps += [ - "//media/cdm/library_cdm:clearkeycdmadapter", + "//media/cdm/library_cdm/clear_key_cdm", "//third_party/widevine/cdm:widevinecdmadapter", ] } @@ -5432,7 +5433,7 @@ if (enable_library_cdms) { deps += [ "//media/cdm:cdm_paths" ] data_deps = [ - "//media/cdm/library_cdm:clearkeycdmadapter", + "//media/cdm/library_cdm/clear_key_cdm", "//third_party/widevine/cdm:widevinecdmadapter", ] }
diff --git a/chrome/test/data/extensions/content_verifier/has_default_resource.crx b/chrome/test/data/extensions/content_verifier/has_default_resource.crx new file mode 100644 index 0000000..68a5591 --- /dev/null +++ b/chrome/test/data/extensions/content_verifier/has_default_resource.crx Binary files differ
diff --git a/chrome/test/data/extensions/content_verifier/has_default_resource.crx.INFO b/chrome/test/data/extensions/content_verifier/has_default_resource.crx.INFO new file mode 100644 index 0000000..28e7ec24 --- /dev/null +++ b/chrome/test/data/extensions/content_verifier/has_default_resource.crx.INFO
@@ -0,0 +1,9 @@ +Information about has_default_resource.crx: + +A test extension downloaded from webstore. +extension_id: bbmokfifpjdhnmacojglcoihoagfmcll +It has background.js as background script. On ExtensionLoad, the extension will +trigger this resource load. +There are two other resources inside the extension: + - page.html + - script.js
diff --git a/chrome/test/data/extensions/content_verifier/no_default_resources.crx b/chrome/test/data/extensions/content_verifier/no_default_resources.crx new file mode 100644 index 0000000..5a80e02 --- /dev/null +++ b/chrome/test/data/extensions/content_verifier/no_default_resources.crx Binary files differ
diff --git a/chrome/test/data/extensions/content_verifier/no_default_resources.crx.INFO b/chrome/test/data/extensions/content_verifier/no_default_resources.crx.INFO new file mode 100644 index 0000000..d8b9a1157d --- /dev/null +++ b/chrome/test/data/extensions/content_verifier/no_default_resources.crx.INFO
@@ -0,0 +1,9 @@ +Information about no_default_resources.crx: + +A test extension downloaded from webstore. +extension_id: lpibhlnkgcbcgdjlaacppnkmmlfpapij +The extension doesn't have any resource that will be loaded by default on +ExtensionLoad. +There are two resources inside the extension: + - page.html + - script.js
diff --git a/chrome/tools/build/chromeos/FILES.cfg b/chrome/tools/build/chromeos/FILES.cfg index 7f936fa..891bb23 100644 --- a/chrome/tools/build/chromeos/FILES.cfg +++ b/chrome/tools/build/chromeos/FILES.cfg
@@ -82,10 +82,6 @@ }, # CDM files (each has an adapter and the actual CDM): { - 'filename': 'libclearkeycdmadapter.so', - 'buildtype': ['dev', 'official'], - }, - { 'filename': 'libclearkeycdm.so', 'buildtype': ['dev', 'official'], },
diff --git a/chrome/tools/build/linux/FILES.cfg b/chrome/tools/build/linux/FILES.cfg index 3a5d6186..afd951a 100644 --- a/chrome/tools/build/linux/FILES.cfg +++ b/chrome/tools/build/linux/FILES.cfg
@@ -93,10 +93,6 @@ }, # CDM files (each has an adapter and the actual CDM): { - 'filename': 'libclearkeycdmadapter.so', - 'buildtype': ['dev', 'official'], - }, - { 'filename': 'libclearkeycdm.so', 'buildtype': ['dev', 'official'], },
diff --git a/chromecast/browser/extensions/cast_extension_system.cc b/chromecast/browser/extensions/cast_extension_system.cc index 32712b0..17d0af4 100644 --- a/chromecast/browser/extensions/cast_extension_system.cc +++ b/chromecast/browser/extensions/cast_extension_system.cc
@@ -26,6 +26,7 @@ #include "extensions/browser/renderer_startup_helper.h" #include "extensions/browser/runtime_data.h" #include "extensions/browser/service_worker_manager.h" +#include "extensions/browser/shared_user_script_master.h" #include "extensions/browser/value_store/value_store_factory_impl.h" #include "extensions/common/api/app_runtime.h" #include "extensions/common/constants.h" @@ -193,6 +194,9 @@ app_sorting_ = std::make_unique<NullAppSorting>(); RendererStartupHelperFactory::GetForBrowserContext(browser_context_); + + shared_user_script_master_ = + std::make_unique<SharedUserScriptMaster>(browser_context_); } void CastExtensionSystem::InitForIncognitoProfile() { @@ -216,7 +220,7 @@ } SharedUserScriptMaster* CastExtensionSystem::shared_user_script_master() { - return nullptr; + return shared_user_script_master_.get(); } StateStore* CastExtensionSystem::state_store() {
diff --git a/chromecast/browser/extensions/cast_extension_system.h b/chromecast/browser/extensions/cast_extension_system.h index 66e0ce2..3026c14 100644 --- a/chromecast/browser/extensions/cast_extension_system.h +++ b/chromecast/browser/extensions/cast_extension_system.h
@@ -97,6 +97,7 @@ std::unique_ptr<RuntimeData> runtime_data_; std::unique_ptr<QuotaService> quota_service_; std::unique_ptr<AppSorting> app_sorting_; + std::unique_ptr<SharedUserScriptMaster> shared_user_script_master_; scoped_refptr<ValueStoreFactory> store_factory_;
diff --git a/chromecast/common/cast_extensions_client.cc b/chromecast/common/cast_extensions_client.cc index 82220380..ee7627f 100644 --- a/chromecast/common/cast_extensions_client.cc +++ b/chromecast/common/cast_extensions_client.cc
@@ -20,6 +20,7 @@ #include "extensions/common/features/manifest_feature.h" #include "extensions/common/features/simple_feature.h" #include "extensions/common/manifest_handler.h" +#include "extensions/common/manifest_handlers/content_scripts_handler.h" #include "extensions/common/permissions/permission_message_provider.h" #include "extensions/common/permissions/permissions_info.h" #include "extensions/common/permissions/permissions_provider.h" @@ -36,6 +37,11 @@ namespace { +void RegisterCastManifestHandlers() { + DCHECK(!ManifestHandler::IsRegistrationFinalized()); + (new ContentScriptsHandler)->Register(); +} + // TODO(jamescook): Refactor ChromePermissionsMessageProvider so we can share // code. For now, this implementation does nothing. class ShellPermissionMessageProvider : public PermissionMessageProvider { @@ -81,6 +87,7 @@ void CastExtensionsClient::Initialize() { RegisterCommonManifestHandlers(); + RegisterCastManifestHandlers(); ManifestHandler::FinalizeRegistration(); // TODO(jamescook): Do we need to whitelist any extensions? @@ -114,6 +121,14 @@ feature->set_channel(version_info::Channel::STABLE); feature->set_extension_types({extensions::Manifest::TYPE_PLATFORM_APP}); provider->AddFeature("cast_url", feature); + + feature = new extensions::ManifestFeature(); + feature->set_name("content_scripts"); + feature->set_channel(version_info::Channel::STABLE); + feature->set_extension_types( + {extensions::Manifest::TYPE_EXTENSION, + extensions::Manifest::TYPE_LEGACY_PACKAGED_APP}); + provider->AddFeature("content_scripts", feature); } else if (name == "permission") { provider = std::make_unique<ShellPermissionFeatureProvider>(); } else if (name == "behavior") {
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index c67de27..65c058bc 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -860,9 +860,10 @@ else { FormData form; FormFieldData field; - if (form_util::FindFormAndFieldForFormControlElement(element, &form, - &field)) { - GetAutofillDriver()->SelectControlDidChange( + const mojom::AutofillDriverPtr& driver = GetAutofillDriver(); + if (driver && form_util::FindFormAndFieldForFormControlElement( + element, &form, &field)) { + driver->SelectControlDidChange( form, field, render_frame()->GetRenderView()->ElementBoundsInWindow(element)); }
diff --git a/components/autofill/core/browser/autofill_experiments.cc b/components/autofill/core/browser/autofill_experiments.cc index 0b48cff..d989cf6 100644 --- a/components/autofill/core/browser/autofill_experiments.cc +++ b/components/autofill/core/browser/autofill_experiments.cc
@@ -222,6 +222,17 @@ return false; } + // Check if sync is not in a permanent error state. + syncer::SyncService::SyncTokenStatus token_status = + sync_service->GetSyncTokenStatus(); + if ((token_status.connection_status == + syncer::ConnectionStatus::CONNECTION_AUTH_ERROR || + token_status.connection_status == + syncer::ConnectionStatus::CONNECTION_SERVER_ERROR) && + token_status.last_get_token_error.IsPersistentError()) { + return false; + } + // Users who have enabled a passphrase have chosen to not make their sync // information accessible to Google. Since upload makes credit card data // available to other Google systems, disable it for passphrase users.
diff --git a/components/autofill/core/browser/autofill_experiments_unittest.cc b/components/autofill/core/browser/autofill_experiments_unittest.cc index ef45b490..bcba1a3 100644 --- a/components/autofill/core/browser/autofill_experiments_unittest.cc +++ b/components/autofill/core/browser/autofill_experiments_unittest.cc
@@ -53,11 +53,28 @@ is_using_secondary_passphrase_ = is_using_secondary_passphrase; } + syncer::SyncService::SyncTokenStatus GetSyncTokenStatus() const override { + syncer::SyncService::SyncTokenStatus token; + + if (is_in_auth_error_) { + token.connection_status = syncer::ConnectionStatus::CONNECTION_AUTH_ERROR; + token.last_get_token_error = + GoogleServiceAuthError::FromServiceError("error"); + } + + return token; + } + + void SetInAuthError(bool is_in_auth_error) { + is_in_auth_error_ = is_in_auth_error; + } + private: bool can_sync_start_; syncer::ModelTypeSet preferred_data_types_; bool is_engine_initialized_; bool is_using_secondary_passphrase_; + bool is_in_auth_error_ = false; }; } // namespace @@ -100,6 +117,11 @@ EXPECT_FALSE(IsCreditCardUploadEnabled()); } +TEST_F(AutofillExperimentsTest, DenyUpload_AuthError) { + sync_service_.SetInAuthError(true); + EXPECT_FALSE(IsCreditCardUploadEnabled()); +} + TEST_F(AutofillExperimentsTest, DenyUpload_SyncServiceDoesNotHaveAutofillProfilePreferredDataType) { sync_service_.SetPreferredDataTypes(syncer::ModelTypeSet());
diff --git a/components/browser_watcher/postmortem_report_collector.cc b/components/browser_watcher/postmortem_report_collector.cc index 1155c054..3b83a79 100644 --- a/components/browser_watcher/postmortem_report_collector.cc +++ b/components/browser_watcher/postmortem_report_collector.cc
@@ -224,19 +224,17 @@ DCHECK(report_proto); // Prepare a crashpad report. - CrashReportDatabase::NewReport* new_report = nullptr; + std::unique_ptr<CrashReportDatabase::NewReport> new_report; CrashReportDatabase::OperationStatus database_status = report_database_->PrepareNewCrashReport(&new_report); if (database_status != CrashReportDatabase::kNoError) { LogCollectionStatus(PREPARE_NEW_CRASH_REPORT_FAILED); return; } - CrashReportDatabase::CallErrorWritingCrashReport - call_error_writing_crash_report(report_database_, new_report); // Write the report to a minidump. - if (!WriteReportToMinidump(report_proto, client_id, new_report->uuid, - reinterpret_cast<FILE*>(new_report->handle))) { + if (!WriteReportToMinidump(report_proto, client_id, new_report->ReportID(), + new_report->Writer())) { LogCollectionStatus(WRITE_TO_MINIDUMP_FAILED); return; } @@ -244,10 +242,9 @@ // Finalize the report wrt the report database. Note that this doesn't trigger // an immediate upload, but Crashpad will eventually upload the report (as of // writing, the delay is on the order of up to 15 minutes). - call_error_writing_crash_report.Disarm(); crashpad::UUID unused_report_id; database_status = report_database_->FinishedWritingCrashReport( - new_report, &unused_report_id); + std::move(new_report), &unused_report_id); if (database_status != CrashReportDatabase::kNoError) { LogCollectionStatus(FINISHED_WRITING_CRASH_REPORT_FAILED); return; @@ -260,11 +257,9 @@ StabilityReport* report, const crashpad::UUID& client_id, const crashpad::UUID& report_id, - base::PlatformFile minidump_file) { + crashpad::FileWriterInterface* minidump_file) { DCHECK(report); - - crashpad::WeakFileHandleFileWriter writer(minidump_file); - return WritePostmortemDump(&writer, client_id, report_id, report); + return WritePostmortemDump(minidump_file, client_id, report_id, report); } } // namespace browser_watcher
diff --git a/components/browser_watcher/postmortem_report_collector.h b/components/browser_watcher/postmortem_report_collector.h index 367250a..c01d0aa 100644 --- a/components/browser_watcher/postmortem_report_collector.h +++ b/components/browser_watcher/postmortem_report_collector.h
@@ -16,7 +16,6 @@ #include <vector> #include "base/debug/activity_analyzer.h" -#include "base/files/file.h" #include "base/files/file_path.h" #include "base/gtest_prod_util.h" #include "base/macros.h" @@ -25,6 +24,7 @@ #include "components/browser_watcher/stability_report_extractor.h" #include "components/metrics/system_session_analyzer_win.h" #include "third_party/crashpad/crashpad/client/crash_report_database.h" +#include "third_party/crashpad/crashpad/util/file/file_writer.h" namespace browser_watcher { @@ -94,10 +94,11 @@ void GenerateCrashReport(const crashpad::UUID& client_id, StabilityReport* report_proto); - virtual bool WriteReportToMinidump(StabilityReport* report, - const crashpad::UUID& client_id, - const crashpad::UUID& report_id, - base::PlatformFile minidump_file); + virtual bool WriteReportToMinidump( + StabilityReport* report, + const crashpad::UUID& client_id, + const crashpad::UUID& report_id, + crashpad::FileWriterInterface* minidump_file); std::string product_name_; std::string version_number_;
diff --git a/components/browser_watcher/postmortem_report_collector_unittest.cc b/components/browser_watcher/postmortem_report_collector_unittest.cc index eb4a103..fdb11f6c 100644 --- a/components/browser_watcher/postmortem_report_collector_unittest.cc +++ b/components/browser_watcher/postmortem_report_collector_unittest.cc
@@ -75,7 +75,7 @@ bool(StabilityReport* report, const crashpad::UUID& client_id, const crashpad::UUID& report_id, - base::PlatformFile minidump_file)); + crashpad::FileWriterInterface* minidump_file)); }; class MockSystemSessionAnalyzer : public metrics::SystemSessionAnalyzer {
diff --git a/components/crash/content/app/minidump_with_crashpad_info.cc b/components/crash/content/app/minidump_with_crashpad_info.cc index a6ee276..cd9726b 100644 --- a/components/crash/content/app/minidump_with_crashpad_info.cc +++ b/components/crash/content/app/minidump_with_crashpad_info.cc
@@ -279,9 +279,9 @@ // Appends the full contents of |source| to |dest| from the current position // of |dest|. -bool AppendFileContents(base::File* source, base::PlatformFile dest) { +bool AppendFileContents(base::File* source, crashpad::FileWriter* dest) { DCHECK(source && source->IsValid()); - DCHECK_NE(base::kInvalidPlatformFile, dest); + DCHECK(dest); // Rewind the source. if (source->Seek(base::File::FROM_BEGIN, 0) == -1) @@ -292,16 +292,12 @@ while (true) { int bytes_read = source->ReadAtCurrentPos(&buf[0], static_cast<int>(buf.size())); - if (bytes_read == -1) + if (bytes_read < 0) return false; if (bytes_read == 0) break; - DWORD bytes_written = 0; - // Due to handle instrumentation, the destination can't be wrapped in - // a base::File, so we go basic Win32 API here. - if (!WriteFile(dest, &buf[0], bytes_read, &bytes_written, nullptr) || - static_cast<int>(bytes_written) != bytes_read) { + if (!dest->Write(&buf[0], static_cast<size_t>(bytes_read))) { return false; } } @@ -323,16 +319,12 @@ if (!database) return false; - crashpad::CrashReportDatabase::NewReport* report = nullptr; + std::unique_ptr<crashpad::CrashReportDatabase::NewReport> report; crashpad::CrashReportDatabase::OperationStatus status = database->PrepareNewCrashReport(&report); if (status != crashpad::CrashReportDatabase::kNoError) return false; - // Make sure we release the report on early exit. - crashpad::CrashReportDatabase::CallErrorWritingCrashReport on_error( - database.get(), report); - crashpad::UUID client_id; crashpad::Settings* settings = database->GetSettings(); if (settings) { @@ -357,16 +349,14 @@ // Write the minidump to the temp file, and then copy the data to the // Crashpad-provided handle, as the latter is only open for write. if (!MiniDumpWriteDumpWithCrashpadInfo(process, minidump_type, exc_info, - crash_keys, client_id, report->uuid, - &dump_file) || - !AppendFileContents(&dump_file, report->handle)) { + crash_keys, client_id, + report->ReportID(), &dump_file) || + !AppendFileContents(&dump_file, report->Writer())) { return false; } - on_error.Disarm(); - crashpad::UUID report_id = {}; - status = database->FinishedWritingCrashReport(report, &report_id); + status = database->FinishedWritingCrashReport(std::move(report), &report_id); if (status != crashpad::CrashReportDatabase::kNoError) return false;
diff --git a/components/crash/core/common/BUILD.gn b/components/crash/core/common/BUILD.gn index 4f67529f..c8e02ebf 100644 --- a/components/crash/core/common/BUILD.gn +++ b/components/crash/core/common/BUILD.gn
@@ -2,6 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/buildflag_header.gni") + +declare_args() { + # If set to true, this will stub out and disable the entire crash key system. + use_crash_key_stubs = is_fuchsia +} + group("common") { public_deps = [ ":crash_key", @@ -13,15 +20,22 @@ } } -use_crashpad = is_mac || is_win -use_stubs = is_fuchsia +use_crashpad_annotation = (is_mac || is_win) && !use_crash_key_stubs + +buildflag_header("crash_buildflags") { + header = "crash_buildflags.h" + flags = [ + "USE_CRASHPAD_ANNOTATION=$use_crashpad_annotation", + "USE_CRASH_KEY_STUBS=$use_crash_key_stubs", + ] +} # Crashpad's annotation system can store data on a per-module basis (i.e., # in different shared libraries in the component build) without issue. The # Breakpad implementation uses a static global variable, so ensure there is # only one instance of the symbol in the component build by making this # target a component. -if (use_stubs || use_crashpad) { +if (use_crash_key_stubs || use_crashpad_annotation) { crash_key_target_type = "static_library" } else { crash_key_target_type = "component" @@ -51,14 +65,15 @@ } deps = [ + ":crash_buildflags", "//base", ] - if (use_crashpad) { + if (use_crash_key_stubs) { + sources += [ "crash_key_stubs.cc" ] + } else if (use_crashpad_annotation) { sources += [ "crash_key_crashpad.cc" ] deps += [ "//third_party/crashpad/crashpad/client" ] - } else if (use_stubs) { - sources += [ "crash_key_stubs.cc" ] } else { include_dirs = [ "//third_party/breakpad/breakpad/src" ]
diff --git a/components/crash/core/common/crash_key.h b/components/crash/core/common/crash_key.h index 951c7e9..b37987e 100644 --- a/components/crash/core/common/crash_key.h +++ b/components/crash/core/common/crash_key.h
@@ -13,17 +13,14 @@ #include "base/macros.h" #include "base/strings/string_piece.h" #include "build/build_config.h" +#include "components/crash/core/common/crash_buildflags.h" #include "components/crash/core/common/crash_export.h" // The crash key interface exposed by this file is the same as the Crashpad // Annotation interface. Because not all platforms use Crashpad yet, a // source-compatible interface is provided on top of the older Breakpad // storage mechanism. -#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) -#define USE_CRASHPAD_ANNOTATION 1 -#endif - -#if defined(USE_CRASHPAD_ANNOTATION) +#if BUILDFLAG(USE_CRASHPAD_ANNOTATION) #include "third_party/crashpad/crashpad/client/annotation.h" #endif @@ -61,7 +58,7 @@ // g_operation_id.Clear() // } // \endcode -#if defined(USE_CRASHPAD_ANNOTATION) +#if BUILDFLAG(USE_CRASHPAD_ANNOTATION) template <crashpad::Annotation::ValueSizeType MaxLength> using CrashKeyString = crashpad::StringAnnotation<MaxLength>; @@ -175,7 +172,7 @@ // } class ScopedCrashKeyString { public: -#if defined(USE_CRASHPAD_ANNOTATION) +#if BUILDFLAG(USE_CRASHPAD_ANNOTATION) using CrashKeyType = crashpad::Annotation; #else using CrashKeyType = internal::CrashKeyStringImpl; @@ -229,6 +226,4 @@ } // namespace crash_reporter -#undef USE_CRASHPAD_ANNOTATION - #endif // COMPONENTS_CRASH_CORE_COMMON_CRASH_KEY_H_
diff --git a/components/crash/core/common/crash_key_stubs.cc b/components/crash/core/common/crash_key_stubs.cc index f978394..77fe36e7 100644 --- a/components/crash/core/common/crash_key_stubs.cc +++ b/components/crash/core/common/crash_key_stubs.cc
@@ -8,8 +8,8 @@ #include "build/build_config.h" #include "components/crash/core/common/crash_key.h" -#if !defined(OS_FUCHSIA) -#error "This file is only for OS_FUCHSIA." +#if !BUILDFLAG(USE_CRASH_KEY_STUBS) +#error "This file should only be compiled when using stubs." #endif namespace crash_reporter {
diff --git a/components/patch_service/BUILD.gn b/components/patch_service/BUILD.gn index ff82f4b..29906df 100644 --- a/components/patch_service/BUILD.gn +++ b/components/patch_service/BUILD.gn
@@ -15,7 +15,7 @@ deps = [ "//base", - "//components/filesystem/public/interfaces", + "//components/services/filesystem/public/interfaces", "//courgette:courgette_lib", "//mojo/public/cpp/bindings", ]
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 892f7be2..2a42008 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -31,7 +31,6 @@ # 'main' - a boolean value # 'list' - a list of string values # 'dict' - a dictionary value, containing other values indexed by strings -# NOTE: This type is not supported yet. https://crbug.com/108992 # 'external' - a policy that references external data. # NOTE: This type is currently supported on Chrome OS only. # @@ -175,11 +174,19 @@ # This setting applies to Chrome OS only. If the setting is missing, both # types are assumed. The array must not be empty. # -# Enterprise defaults: +# Enterprise defaults for user policy: # For managed users on Chrome OS (i.e. users receiving user policy from the # cloud), if the optional key 'default_for_enterprise_users' is set, its value # is applied as mandatory policy unless a different setting is received from -# the cloud. +# the cloud. This default value handling is automatically enforced by the +# policy stack when filling the PolicyMap (specifically, by the generated +# function SetEnterpriseUsersDefaults). +# +# Enterprise defaults for device policy: +# The optional key 'default_for_managed_devices_doc_only' can be used to +# document a differing default value for devices enrolled into enterprise +# management. This is for documentation only - the enrollment-dependent +# handling must be manually implemented. 'risk_tag_definitions' : [ # All following tags are ordered by severity of their impact. @@ -8355,6 +8362,7 @@ 'dynamic_refresh': False, }, 'example_value': True, + 'default_for_managed_devices_doc_only': False, 'id': 219, 'caption': '''Enable supervised users''', 'tags': [], @@ -11358,6 +11366,7 @@ 'dynamic_refresh': True, }, 'example_value': True, + 'default_for_managed_devices_doc_only': False, 'id': 421, 'caption': '''Allow devices to run virtual machines on Chrome OS''', 'tags': ['system-security'],
diff --git a/components/policy/tools/syntax_check_policy_template_json.py b/components/policy/tools/syntax_check_policy_template_json.py index f6ae6479..02977e8 100755 --- a/components/policy/tools/syntax_check_policy_template_json.py +++ b/components/policy/tools/syntax_check_policy_template_json.py
@@ -185,8 +185,9 @@ 'supported_on', 'label', 'policies', 'items', 'example_value', 'features', 'deprecated', 'future', 'id', 'schema', 'max_size', 'tags', - 'default_for_enterprise_users', 'arc_support', - 'supported_chrome_os_management'): + 'default_for_enterprise_users', + 'default_for_managed_devices_doc_only', + 'arc_support', 'supported_chrome_os_management'): self.warning_count += 1 print ('In policy %s: Warning: Unknown key: %s' % (policy.get('name'), key)) @@ -288,6 +289,28 @@ self._Error('per_profile attribute should not be set ' 'for policies with device_only=True') + # If 'device only' policy is on, 'default_for_enterprise_users' shouldn't + # exist. + if (policy.get('device_only', False) and + 'default_for_enterprise_users' in policy): + self._Error('default_for_enteprise_users should not be set ' + 'for policies with device_only=True. Please use ' + 'default_for_managed_devices_doc_only to document a' + 'differing default value for enrolled devices. Please note ' + 'that default_for_managed_devices_doc_only is for ' + 'documentation only - it has no side effects, so you will ' + ' still have to implement the enrollment-dependent default ' + 'value handling yourself in all places where the device ' + 'policy proto is evaluated. This will probably include ' + 'device_policy_decoder_chromeos.cc for chrome, but could ' + 'also have to done in other components if they read the ' + 'proto directly. Details: crbug.com/809653') + + if (not policy.get('device_only', False) and + 'default_for_managed_devices_doc_only' in policy): + self._Error('default_for_managed_devices_doc_only should only be used ' + 'with policies that have device_only=True.') + # All policies must declare whether they allow changes at runtime. self._CheckContains(features, 'dynamic_refresh', bool, container_name='features',
diff --git a/components/policy_strings.grdp b/components/policy_strings.grdp index 38f3d25..b73107b 100644 --- a/components/policy_strings.grdp +++ b/components/policy_strings.grdp
@@ -228,6 +228,12 @@ </message> <!-- chrome://policy-tool --> + <message name="IDS_POLICY_TOOL_CANCEL_RENAME" desc="Button to cancel the dialog that appears in rename session."> + Cancel + </message> + <message name="IDS_POLICY_TOOL_CONFIRM_RENAME" desc="Button that confirm a rename session."> + Confirm + </message> <message name="IDS_POLICY_TOOL_TITLE" desc="Admin page title and the title of the section that lists policies."> Policy management </message> @@ -240,6 +246,12 @@ <message name="IDS_POLICY_TOOL_LOAD_SESSION" desc="Label for the button that loads specified session."> Load session </message> + <message name="IDS_POLICY_TOOL_REMOVE_SESSION" desc="Label for the button that removes specified session."> + Remove + </message> + <message name="IDS_POLICY_TOOL_RENAME_SESSION" desc="Label for the button that renames specified session."> + Rename + </message> <message name="IDS_POLICY_TOOL_SESSION_NAME_PLACEHOLDER" desc="Placeholder for the input field that lets the user change policy management sessions."> Session name </message> @@ -258,6 +270,18 @@ <message name="IDS_POLICY_TOOL_DELETE_FAILED" desc="A message that is shown to the user when deleting the session fails because the session name that is sent from Javascript is invalid."> The session with this name is not valid for deletion. </message> + <message name="IDS_POLICY_TOOL_SESSION_NOT_EXIST" desc="A message that is shown to the user when + the selected session name does not exist."> + The selected session does not exist. + </message> + <message name="IDS_POLICY_TOOL_SESSION_EXIST" desc="A message that is show to the user when + there is another session with the same name in a renaming session."> + This session name already exists. + </message> + <message name="IDS_POLICY_TOOL_RENAME_FAILED" desc="A message that is shown to the user when + renaming the session fails because the function that rename the file failed."> + Failed to rename the session. + </message> <!-- chrome://policy --> <message name="IDS_POLICY_TITLE" desc="Page title and the title of the section that lists policies."> Policies
diff --git a/components/proxy_config/pref_proxy_config_tracker_impl.cc b/components/proxy_config/pref_proxy_config_tracker_impl.cc index 2a740f9..aee58b46b 100644 --- a/components/proxy_config/pref_proxy_config_tracker_impl.cc +++ b/components/proxy_config/pref_proxy_config_tracker_impl.cc
@@ -22,12 +22,11 @@ namespace { -// TODO(rhalavati): Update annotation. constexpr net::NetworkTrafficAnnotationTag kSettingsProxyConfigTrafficAnnotation = net::DefineNetworkTrafficAnnotation("proxy_config_settings", R"( semantics { - sender: "Preferences Proxy Config" + sender: "Proxy Config" description: "Creates a proxy based on configuration received from settings." trigger:
diff --git a/components/filesystem/BUILD.gn b/components/services/filesystem/BUILD.gn similarity index 92% rename from components/filesystem/BUILD.gn rename to components/services/filesystem/BUILD.gn index c070209c..638b7ec1 100644 --- a/components/filesystem/BUILD.gn +++ b/components/services/filesystem/BUILD.gn
@@ -26,7 +26,7 @@ deps = [ "//base", - "//components/filesystem/public/interfaces", + "//components/services/filesystem/public/interfaces", "//mojo/common", "//mojo/common:common_base", "//mojo/public/cpp/system", @@ -48,7 +48,7 @@ deps = [ ":lib", "//base", - "//components/filesystem/public/interfaces", + "//components/services/filesystem/public/interfaces", "//mojo/common", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", @@ -73,7 +73,7 @@ deps = [ "//base", - "//components/filesystem/public/interfaces", + "//components/services/filesystem/public/interfaces", "//mojo/common", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system",
diff --git a/components/filesystem/DEPS b/components/services/filesystem/DEPS similarity index 100% rename from components/filesystem/DEPS rename to components/services/filesystem/DEPS
diff --git a/components/filesystem/OWNERS b/components/services/filesystem/OWNERS similarity index 100% rename from components/filesystem/OWNERS rename to components/services/filesystem/OWNERS
diff --git a/components/filesystem/directory_impl.cc b/components/services/filesystem/directory_impl.cc similarity index 98% rename from components/filesystem/directory_impl.cc rename to components/services/filesystem/directory_impl.cc index 21e4adf..7c0b898 100644 --- a/components/filesystem/directory_impl.cc +++ b/components/services/filesystem/directory_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/filesystem/directory_impl.h" +#include "components/services/filesystem/directory_impl.h" #include <memory> #include <string> @@ -15,9 +15,9 @@ #include "base/files/scoped_temp_dir.h" #include "base/logging.h" #include "build/build_config.h" -#include "components/filesystem/file_impl.h" -#include "components/filesystem/lock_table.h" -#include "components/filesystem/util.h" +#include "components/services/filesystem/file_impl.h" +#include "components/services/filesystem/lock_table.h" +#include "components/services/filesystem/util.h" #include "mojo/public/cpp/bindings/strong_binding.h" namespace filesystem {
diff --git a/components/filesystem/directory_impl.h b/components/services/filesystem/directory_impl.h similarity index 89% rename from components/filesystem/directory_impl.h rename to components/services/filesystem/directory_impl.h index afdd30c8..03e56e16 100644 --- a/components/filesystem/directory_impl.h +++ b/components/services/filesystem/directory_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_FILESYSTEM_DIRECTORY_IMPL_H_ -#define COMPONENTS_FILESYSTEM_DIRECTORY_IMPL_H_ +#ifndef COMPONENTS_SERVICES_FILESYSTEM_DIRECTORY_IMPL_H_ +#define COMPONENTS_SERVICES_FILESYSTEM_DIRECTORY_IMPL_H_ #include <stdint.h> @@ -12,8 +12,8 @@ #include "base/files/file_path.h" #include "base/files/scoped_file.h" #include "base/macros.h" -#include "components/filesystem/public/interfaces/directory.mojom.h" -#include "components/filesystem/shared_temp_dir.h" +#include "components/services/filesystem/public/interfaces/directory.mojom.h" +#include "components/services/filesystem/shared_temp_dir.h" #include "mojo/public/cpp/bindings/interface_request.h" namespace filesystem { @@ -78,4 +78,4 @@ } // namespace filesystem -#endif // COMPONENTS_FILESYSTEM_DIRECTORY_IMPL_H_ +#endif // COMPONENTS_SERVICES_FILESYSTEM_DIRECTORY_IMPL_H_
diff --git a/components/filesystem/directory_impl_unittest.cc b/components/services/filesystem/directory_impl_unittest.cc similarity index 99% rename from components/filesystem/directory_impl_unittest.cc rename to components/services/filesystem/directory_impl_unittest.cc index b129972..0a051df608 100644 --- a/components/filesystem/directory_impl_unittest.cc +++ b/components/services/filesystem/directory_impl_unittest.cc
@@ -9,7 +9,7 @@ #include <string> #include "base/macros.h" -#include "components/filesystem/files_test_base.h" +#include "components/services/filesystem/files_test_base.h" namespace filesystem { namespace {
diff --git a/components/filesystem/file_impl.cc b/components/services/filesystem/file_impl.cc similarity index 96% rename from components/filesystem/file_impl.cc rename to components/services/filesystem/file_impl.cc index 1e726f3..6346501 100644 --- a/components/filesystem/file_impl.cc +++ b/components/services/filesystem/file_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/filesystem/file_impl.h" +#include "components/services/filesystem/file_impl.h" #include <stddef.h> #include <stdint.h> @@ -16,9 +16,9 @@ #include "base/files/scoped_file.h" #include "base/logging.h" #include "build/build_config.h" -#include "components/filesystem/lock_table.h" -#include "components/filesystem/shared_temp_dir.h" -#include "components/filesystem/util.h" +#include "components/services/filesystem/lock_table.h" +#include "components/services/filesystem/shared_temp_dir.h" +#include "components/services/filesystem/util.h" #include "mojo/public/cpp/bindings/strong_binding.h" static_assert(sizeof(off_t) <= sizeof(int64_t), "off_t too big"); @@ -169,8 +169,8 @@ const char* buf = (bytes_to_write.size() > 0) ? reinterpret_cast<const char*>(&bytes_to_write.front()) : nullptr; - int num_bytes_written = file_.WriteAtCurrentPos( - buf, static_cast<int>(bytes_to_write.size())); + int num_bytes_written = + file_.WriteAtCurrentPos(buf, static_cast<int>(bytes_to_write.size())); if (num_bytes_written < 0) { std::move(callback).Run(base::File::Error::FILE_ERROR_FAILED, 0); return;
diff --git a/components/filesystem/file_impl.h b/components/services/filesystem/file_impl.h similarity index 91% rename from components/filesystem/file_impl.h rename to components/services/filesystem/file_impl.h index 3b7db2ea2..adb1491e 100644 --- a/components/filesystem/file_impl.h +++ b/components/services/filesystem/file_impl.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_FILESYSTEM_FILE_IMPL_H_ -#define COMPONENTS_FILESYSTEM_FILE_IMPL_H_ +#ifndef COMPONENTS_SERVICES_FILESYSTEM_FILE_IMPL_H_ +#define COMPONENTS_SERVICES_FILESYSTEM_FILE_IMPL_H_ #include <stdint.h> @@ -11,7 +11,7 @@ #include "base/files/scoped_file.h" #include "base/macros.h" #include "build/build_config.h" -#include "components/filesystem/public/interfaces/directory.mojom.h" +#include "components/services/filesystem/public/interfaces/directory.mojom.h" #include "mojo/public/cpp/bindings/interface_request.h" namespace base { @@ -83,4 +83,4 @@ } // namespace filesystem -#endif // COMPONENTS_FILESYSTEM_FILE_IMPL_H_ +#endif // COMPONENTS_SERVICES_FILESYSTEM_FILE_IMPL_H_
diff --git a/components/filesystem/file_impl_unittest.cc b/components/services/filesystem/file_impl_unittest.cc similarity index 99% rename from components/filesystem/file_impl_unittest.cc rename to components/services/filesystem/file_impl_unittest.cc index 32410be..1aab2bb3 100644 --- a/components/filesystem/file_impl_unittest.cc +++ b/components/services/filesystem/file_impl_unittest.cc
@@ -8,7 +8,7 @@ #include <vector> #include "base/files/file.h" -#include "components/filesystem/files_test_base.h" +#include "components/services/filesystem/files_test_base.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "mojo/public/cpp/bindings/type_converter.h"
diff --git a/components/filesystem/file_system_app.cc b/components/services/filesystem/file_system_app.cc similarity index 90% rename from components/filesystem/file_system_app.cc rename to components/services/filesystem/file_system_app.cc index 69965c4..d5a24f0 100644 --- a/components/filesystem/file_system_app.cc +++ b/components/services/filesystem/file_system_app.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/filesystem/file_system_app.h" +#include "components/services/filesystem/file_system_app.h" #include <memory> @@ -34,7 +34,7 @@ const char kUserDataDir[] = "user-data-dir"; -} // namespace filesystem +} // namespace FileSystemApp::FileSystemApp() : lock_table_(new LockTable) { registry_.AddInterface<mojom::FileSystem>( @@ -61,7 +61,7 @@ std::move(request)); } -//static +// static base::FilePath FileSystemApp::GetUserDataDir() { base::FilePath path; @@ -77,9 +77,8 @@ CHECK(PathService::Get(base::DIR_ANDROID_APP_DATA, &path)); #elif defined(OS_LINUX) std::unique_ptr<base::Environment> env(base::Environment::Create()); - path = base::nix::GetXDGDirectory(env.get(), - base::nix::kXdgConfigHomeEnvVar, - base::nix::kDotConfigDir); + path = base::nix::GetXDGDirectory( + env.get(), base::nix::kXdgConfigHomeEnvVar, base::nix::kDotConfigDir); #else NOTIMPLEMENTED(); #endif
diff --git a/components/filesystem/file_system_app.h b/components/services/filesystem/file_system_app.h similarity index 73% rename from components/filesystem/file_system_app.h rename to components/services/filesystem/file_system_app.h index e91baa5..84d9d9bf 100644 --- a/components/filesystem/file_system_app.h +++ b/components/services/filesystem/file_system_app.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_FILESYSTEM_FILE_SYSTEM_APP_H_ -#define COMPONENTS_FILESYSTEM_FILE_SYSTEM_APP_H_ +#ifndef COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_APP_H_ +#define COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_APP_H_ #include "base/macros.h" -#include "components/filesystem/directory_impl.h" -#include "components/filesystem/file_system_impl.h" -#include "components/filesystem/lock_table.h" -#include "components/filesystem/public/interfaces/file_system.mojom.h" +#include "components/services/filesystem/directory_impl.h" +#include "components/services/filesystem/file_system_impl.h" +#include "components/services/filesystem/lock_table.h" +#include "components/services/filesystem/public/interfaces/file_system.mojom.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/service.h" @@ -44,4 +44,4 @@ } // namespace filesystem -#endif // COMPONENTS_FILESYSTEM_FILE_SYSTEM_APP_H_ +#endif // COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_APP_H_
diff --git a/components/filesystem/file_system_impl.cc b/components/services/filesystem/file_system_impl.cc similarity index 91% rename from components/filesystem/file_system_impl.cc rename to components/services/filesystem/file_system_impl.cc index 34aa7388..ef857e93 100644 --- a/components/filesystem/file_system_impl.cc +++ b/components/services/filesystem/file_system_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/filesystem/file_system_impl.h" +#include "components/services/filesystem/file_system_impl.h" #include <stddef.h> @@ -16,8 +16,8 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "build/build_config.h" -#include "components/filesystem/directory_impl.h" -#include "components/filesystem/lock_table.h" +#include "components/services/filesystem/directory_impl.h" +#include "components/services/filesystem/lock_table.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/service_manager/public/cpp/identity.h" #include "url/gurl.h" @@ -31,8 +31,7 @@ lock_table_(std::move(lock_table)), persistent_dir_(persistent_dir) {} -FileSystemImpl::~FileSystemImpl() { -} +FileSystemImpl::~FileSystemImpl() {} void FileSystemImpl::OpenTempDirectory(mojom::DirectoryRequest directory, OpenTempDirectoryCallback callback) {
diff --git a/components/filesystem/file_system_impl.h b/components/services/filesystem/file_system_impl.h similarity index 80% rename from components/filesystem/file_system_impl.h rename to components/services/filesystem/file_system_impl.h index 6538077..2b30006c 100644 --- a/components/filesystem/file_system_impl.h +++ b/components/services/filesystem/file_system_impl.h
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_FILESYSTEM_FILE_SYSTEM_IMPL_H_ -#define COMPONENTS_FILESYSTEM_FILE_SYSTEM_IMPL_H_ +#ifndef COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_IMPL_H_ +#define COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_IMPL_H_ #include "base/files/file_path.h" #include "base/macros.h" -#include "components/filesystem/public/interfaces/file_system.mojom.h" -#include "components/filesystem/shared_temp_dir.h" +#include "components/services/filesystem/public/interfaces/file_system.mojom.h" +#include "components/services/filesystem/shared_temp_dir.h" #include "mojo/public/cpp/bindings/interface_request.h" namespace base { @@ -51,4 +51,4 @@ } // namespace filesystem -#endif // COMPONENTS_FILESYSTEM_FILE_SYSTEM_IMPL_H_ +#endif // COMPONENTS_SERVICES_FILESYSTEM_FILE_SYSTEM_IMPL_H_
diff --git a/components/filesystem/files_test_base.cc b/components/services/filesystem/files_test_base.cc similarity index 68% rename from components/filesystem/files_test_base.cc rename to components/services/filesystem/files_test_base.cc index 5e3b356..a8b0b0f 100644 --- a/components/filesystem/files_test_base.cc +++ b/components/services/filesystem/files_test_base.cc
@@ -2,22 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/filesystem/files_test_base.h" +#include "components/services/filesystem/files_test_base.h" #include <utility> -#include "components/filesystem/public/interfaces/directory.mojom.h" -#include "components/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/public/interfaces/directory.mojom.h" +#include "components/services/filesystem/public/interfaces/types.mojom.h" #include "services/service_manager/public/cpp/connector.h" namespace filesystem { -FilesTestBase::FilesTestBase() - : ServiceTest("filesystem_service_unittests") { -} +FilesTestBase::FilesTestBase() : ServiceTest("filesystem_service_unittests") {} -FilesTestBase::~FilesTestBase() { -} +FilesTestBase::~FilesTestBase() {} void FilesTestBase::SetUp() { ServiceTest::SetUp();
diff --git a/components/filesystem/files_test_base.h b/components/services/filesystem/files_test_base.h similarity index 82% rename from components/filesystem/files_test_base.h rename to components/services/filesystem/files_test_base.h index d77acda..1f896c5 100644 --- a/components/filesystem/files_test_base.h +++ b/components/services/filesystem/files_test_base.h
@@ -2,20 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_FILESYSTEM_FILES_TEST_BASE_H_ -#define COMPONENTS_FILESYSTEM_FILES_TEST_BASE_H_ +#ifndef COMPONENTS_SERVICES_FILESYSTEM_FILES_TEST_BASE_H_ +#define COMPONENTS_SERVICES_FILESYSTEM_FILES_TEST_BASE_H_ #include <utility> #include "base/bind.h" #include "base/macros.h" -#include "components/filesystem/public/interfaces/file_system.mojom.h" +#include "components/services/filesystem/public/interfaces/file_system.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/service_manager/public/cpp/service_test.h" namespace filesystem { -template <typename... Args> void IgnoreAllArgs(Args&&... args) {} +template <typename... Args> +void IgnoreAllArgs(Args&&... args) {} template <typename... Args> void DoCaptures(Args*... out_args, Args... in_args) { @@ -60,4 +61,4 @@ } // namespace filesystem -#endif // COMPONENTS_FILESYSTEM_FILES_TEST_BASE_H_ +#endif // COMPONENTS_SERVICES_FILESYSTEM_FILES_TEST_BASE_H_
diff --git a/components/filesystem/lock_table.cc b/components/services/filesystem/lock_table.cc similarity index 94% rename from components/filesystem/lock_table.cc rename to components/services/filesystem/lock_table.cc index badbbad..a3402a9e 100644 --- a/components/filesystem/lock_table.cc +++ b/components/services/filesystem/lock_table.cc
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/filesystem/lock_table.h" +#include "components/services/filesystem/lock_table.h" #include "build/build_config.h" -#include "components/filesystem/file_impl.h" +#include "components/services/filesystem/file_impl.h" namespace filesystem {
diff --git a/components/filesystem/lock_table.h b/components/services/filesystem/lock_table.h similarity index 88% rename from components/filesystem/lock_table.h rename to components/services/filesystem/lock_table.h index 73674ac2..5248960 100644 --- a/components/filesystem/lock_table.h +++ b/components/services/filesystem/lock_table.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_FILESYSTEM_LOCK_TABLE_H_ -#define COMPONENTS_FILESYSTEM_LOCK_TABLE_H_ +#ifndef COMPONENTS_SERVICES_FILESYSTEM_LOCK_TABLE_H_ +#define COMPONENTS_SERVICES_FILESYSTEM_LOCK_TABLE_H_ #include <set> @@ -45,4 +45,4 @@ } // namespace filesystem -#endif // COMPONENTS_FILESYSTEM_LOCK_TABLE_H_ +#endif // COMPONENTS_SERVICES_FILESYSTEM_LOCK_TABLE_H_
diff --git a/components/filesystem/main.cc b/components/services/filesystem/main.cc similarity index 88% rename from components/filesystem/main.cc rename to components/services/filesystem/main.cc index 781dfb64..62359c0 100644 --- a/components/filesystem/main.cc +++ b/components/services/filesystem/main.cc
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/macros.h" -#include "components/filesystem/file_system_app.h" #include "services/service_manager/public/c/main.h" +#include "base/macros.h" +#include "components/services/filesystem/file_system_app.h" #include "services/service_manager/public/cpp/service_runner.h" MojoResult ServiceMain(MojoHandle request) {
diff --git a/components/filesystem/manifest.json b/components/services/filesystem/manifest.json similarity index 100% rename from components/filesystem/manifest.json rename to components/services/filesystem/manifest.json
diff --git a/components/filesystem/public/interfaces/BUILD.gn b/components/services/filesystem/public/interfaces/BUILD.gn similarity index 100% rename from components/filesystem/public/interfaces/BUILD.gn rename to components/services/filesystem/public/interfaces/BUILD.gn
diff --git a/components/filesystem/public/interfaces/OWNERS b/components/services/filesystem/public/interfaces/OWNERS similarity index 100% rename from components/filesystem/public/interfaces/OWNERS rename to components/services/filesystem/public/interfaces/OWNERS
diff --git a/components/filesystem/public/interfaces/directory.mojom b/components/services/filesystem/public/interfaces/directory.mojom similarity index 96% rename from components/filesystem/public/interfaces/directory.mojom rename to components/services/filesystem/public/interfaces/directory.mojom index 4874ee2c..be8f8d5 100644 --- a/components/filesystem/public/interfaces/directory.mojom +++ b/components/services/filesystem/public/interfaces/directory.mojom
@@ -4,8 +4,8 @@ module filesystem.mojom; -import "components/filesystem/public/interfaces/file.mojom"; -import "components/filesystem/public/interfaces/types.mojom"; +import "components/services/filesystem/public/interfaces/file.mojom"; +import "components/services/filesystem/public/interfaces/types.mojom"; import "mojo/common/file.mojom"; import "mojo/public/mojom/base/file_error.mojom";
diff --git a/components/filesystem/public/interfaces/file.mojom b/components/services/filesystem/public/interfaces/file.mojom similarity index 97% rename from components/filesystem/public/interfaces/file.mojom rename to components/services/filesystem/public/interfaces/file.mojom index 7af8a7cf..7d975db 100644 --- a/components/filesystem/public/interfaces/file.mojom +++ b/components/services/filesystem/public/interfaces/file.mojom
@@ -9,7 +9,7 @@ module filesystem.mojom; -import "components/filesystem/public/interfaces/types.mojom"; +import "components/services/filesystem/public/interfaces/types.mojom"; import "mojo/common/file.mojom"; import "mojo/public/mojom/base/file_error.mojom";
diff --git a/components/filesystem/public/interfaces/file_system.mojom b/components/services/filesystem/public/interfaces/file_system.mojom similarity index 88% rename from components/filesystem/public/interfaces/file_system.mojom rename to components/services/filesystem/public/interfaces/file_system.mojom index 94a023f5..f78793b0 100644 --- a/components/filesystem/public/interfaces/file_system.mojom +++ b/components/services/filesystem/public/interfaces/file_system.mojom
@@ -4,7 +4,7 @@ module filesystem.mojom; -import "components/filesystem/public/interfaces/directory.mojom"; +import "components/services/filesystem/public/interfaces/directory.mojom"; import "mojo/public/mojom/base/file_error.mojom"; interface FileSystem {
diff --git a/components/filesystem/public/interfaces/types.mojom b/components/services/filesystem/public/interfaces/types.mojom similarity index 100% rename from components/filesystem/public/interfaces/types.mojom rename to components/services/filesystem/public/interfaces/types.mojom
diff --git a/components/filesystem/shared_temp_dir.cc b/components/services/filesystem/shared_temp_dir.cc similarity index 87% rename from components/filesystem/shared_temp_dir.cc rename to components/services/filesystem/shared_temp_dir.cc index 375b8b8..6c3f25d 100644 --- a/components/filesystem/shared_temp_dir.cc +++ b/components/services/filesystem/shared_temp_dir.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/filesystem/shared_temp_dir.h" +#include "components/services/filesystem/shared_temp_dir.h" #include "base/files/scoped_temp_dir.h"
diff --git a/components/filesystem/shared_temp_dir.h b/components/services/filesystem/shared_temp_dir.h similarity index 80% rename from components/filesystem/shared_temp_dir.h rename to components/services/filesystem/shared_temp_dir.h index d403f73..15ee84b 100644 --- a/components/filesystem/shared_temp_dir.h +++ b/components/services/filesystem/shared_temp_dir.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_FILESYSTEM_SHARED_TEMP_DIR_H_ -#define COMPONENTS_FILESYSTEM_SHARED_TEMP_DIR_H_ +#ifndef COMPONENTS_SERVICES_FILESYSTEM_SHARED_TEMP_DIR_H_ +#define COMPONENTS_SERVICES_FILESYSTEM_SHARED_TEMP_DIR_H_ #include "base/memory/ref_counted.h" @@ -30,4 +30,4 @@ } // namespace filesystem -#endif // COMPONENTS_FILESYSTEM_SHARED_TEMP_DIR_H_ +#endif // COMPONENTS_SERVICES_FILESYSTEM_SHARED_TEMP_DIR_H_
diff --git a/components/filesystem/test_manifest.json b/components/services/filesystem/test_manifest.json similarity index 100% rename from components/filesystem/test_manifest.json rename to components/services/filesystem/test_manifest.json
diff --git a/components/filesystem/util.cc b/components/services/filesystem/util.cc similarity index 98% rename from components/filesystem/util.cc rename to components/services/filesystem/util.cc index 659b9bb6..475dd25 100644 --- a/components/filesystem/util.cc +++ b/components/services/filesystem/util.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/filesystem/util.h" +#include "components/services/filesystem/util.h" #include <errno.h> #include <fcntl.h>
diff --git a/components/filesystem/util.h b/components/services/filesystem/util.h similarity index 88% rename from components/filesystem/util.h rename to components/services/filesystem/util.h index 8d90847..45ddc933 100644 --- a/components/filesystem/util.h +++ b/components/services/filesystem/util.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_FILESYSTEM_UTIL_H_ -#define COMPONENTS_FILESYSTEM_UTIL_H_ +#ifndef COMPONENTS_SERVICES_FILESYSTEM_UTIL_H_ +#define COMPONENTS_SERVICES_FILESYSTEM_UTIL_H_ #include <stdint.h> #include <string> #include "base/files/file.h" -#include "components/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/public/interfaces/types.mojom.h" namespace filesystem { @@ -48,4 +48,4 @@ } // namespace filesystem -#endif // COMPONENTS_FILESYSTEM_UTIL_H_ +#endif // COMPONENTS_SERVICES_FILESYSTEM_UTIL_H_
diff --git a/components/leveldb/BUILD.gn b/components/services/leveldb/BUILD.gn similarity index 80% rename from components/leveldb/BUILD.gn rename to components/services/leveldb/BUILD.gn index 0b0f2cb..e69401ec 100644 --- a/components/leveldb/BUILD.gn +++ b/components/services/leveldb/BUILD.gn
@@ -21,9 +21,9 @@ ] public_deps = [ - "//components/filesystem/public/interfaces", - "//components/leveldb/public/cpp", - "//components/leveldb/public/interfaces", + "//components/services/filesystem/public/interfaces", + "//components/services/leveldb/public/cpp", + "//components/services/leveldb/public/interfaces", ] deps = [ @@ -43,7 +43,7 @@ deps = [ ":lib", - "//components/leveldb/public/interfaces", + "//components/services/leveldb/public/interfaces", "//mojo/common", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", @@ -67,9 +67,9 @@ deps = [ "//base", - "//components/filesystem/public/interfaces", - "//components/leveldb/public/cpp", - "//components/leveldb/public/interfaces", + "//components/services/filesystem/public/interfaces", + "//components/services/leveldb/public/cpp", + "//components/services/leveldb/public/interfaces", "//mojo/common", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", @@ -80,7 +80,7 @@ data_deps = [ ":leveldb", - "//components/filesystem:filesystem", + "//components/services/filesystem:filesystem", ] } @@ -93,6 +93,6 @@ embedded_services = [ ":test_manifest" ] standalone_services = [ ":manifest", - "//components/filesystem:manifest", + "//components/services/filesystem:manifest", ] }
diff --git a/components/leveldb/DEPS b/components/services/leveldb/DEPS similarity index 71% rename from components/leveldb/DEPS rename to components/services/leveldb/DEPS index 659b133..048eb8af 100644 --- a/components/leveldb/DEPS +++ b/components/services/leveldb/DEPS
@@ -1,5 +1,5 @@ include_rules = [ - "+components/filesystem/public/interfaces", + "+components/services/filesystem/public/interfaces", "+mojo/common", "+mojo/public", "+mojo/util",
diff --git a/components/leveldb/OWNERS b/components/services/leveldb/OWNERS similarity index 100% rename from components/leveldb/OWNERS rename to components/services/leveldb/OWNERS
diff --git a/components/leveldb/env_mojo.cc b/components/services/leveldb/env_mojo.cc similarity index 97% rename from components/leveldb/env_mojo.cc rename to components/services/leveldb/env_mojo.cc index e46931f..2985805 100644 --- a/components/leveldb/env_mojo.cc +++ b/components/services/leveldb/env_mojo.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/leveldb/env_mojo.h" +#include "components/services/leveldb/env_mojo.h" #include <memory> #include <string> @@ -70,9 +70,8 @@ ~MojoSequentialFile() override {} Status Read(size_t n, Slice* result, char* scratch) override { - int bytes_read = file_.ReadAtCurrentPosNoBestEffort( - scratch, - static_cast<int>(n)); + int bytes_read = + file_.ReadAtCurrentPosNoBestEffort(scratch, static_cast<int>(n)); if (bytes_read == -1) { base::File::Error error = base::File::GetLastFileError(); uma_logger_->RecordOSError(leveldb_env::kSequentialFileRead, error); @@ -348,9 +347,9 @@ Status MojoEnv::NewWritableFile(const std::string& fname, WritableFile** result) { TRACE_EVENT1("leveldb", "MojoEnv::NewWritableFile", "fname", fname); - base::File f = - thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kCreateAlways | - filesystem::mojom::kFlagWrite); + base::File f = thread_->OpenFileHandle( + dir_, fname, + filesystem::mojom::kCreateAlways | filesystem::mojom::kFlagWrite); if (!f.IsValid()) { *result = nullptr; RecordOSError(leveldb_env::kNewWritableFile, f.error_details()); @@ -365,9 +364,9 @@ Status MojoEnv::NewAppendableFile(const std::string& fname, WritableFile** result) { TRACE_EVENT1("leveldb", "MojoEnv::NewAppendableFile", "fname", fname); - base::File f = - thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kFlagOpenAlways | - filesystem::mojom::kFlagAppend); + base::File f = thread_->OpenFileHandle( + dir_, fname, + filesystem::mojom::kFlagOpenAlways | filesystem::mojom::kFlagAppend); if (!f.IsValid()) { *result = nullptr; RecordOSError(leveldb_env::kNewAppendableFile, f.error_details());
diff --git a/components/leveldb/env_mojo.h b/components/services/leveldb/env_mojo.h similarity index 92% rename from components/leveldb/env_mojo.h rename to components/services/leveldb/env_mojo.h index a2264d96..9748900cf 100644 --- a/components/leveldb/env_mojo.h +++ b/components/services/leveldb/env_mojo.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_LEVELDB_ENV_MOJO_H_ -#define COMPONENTS_LEVELDB_ENV_MOJO_H_ +#ifndef COMPONENTS_SERVICES_LEVELDB_ENV_MOJO_H_ +#define COMPONENTS_SERVICES_LEVELDB_ENV_MOJO_H_ #include <string> #include <vector> -#include "components/filesystem/public/interfaces/directory.mojom.h" -#include "components/leveldb/leveldb_mojo_proxy.h" +#include "components/services/filesystem/public/interfaces/directory.mojom.h" +#include "components/services/leveldb/leveldb_mojo_proxy.h" #include "third_party/leveldatabase/env_chromium.h" #include "third_party/leveldatabase/src/include/leveldb/env.h" @@ -87,4 +87,4 @@ } // namespace leveldb -#endif // COMPONENTS_LEVELDB_ENV_MOJO_H_ +#endif // COMPONENTS_SERVICES_LEVELDB_ENV_MOJO_H_
diff --git a/components/leveldb/leveldb.typemap b/components/services/leveldb/leveldb.typemap similarity index 66% rename from components/leveldb/leveldb.typemap rename to components/services/leveldb/leveldb.typemap index 52d2f394..4b95769 100644 --- a/components/leveldb/leveldb.typemap +++ b/components/services/leveldb/leveldb.typemap
@@ -2,11 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -mojom = "//components/leveldb/public/interfaces/leveldb.mojom" +mojom = "//components/services/leveldb/public/interfaces/leveldb.mojom" public_headers = [ "//third_party/leveldatabase/env_chromium.h" ] -traits_headers = [ "//components/leveldb/leveldb_struct_traits.h" ] +traits_headers = [ "//components/services/leveldb/leveldb_struct_traits.h" ] sources = [ - "//components/leveldb/leveldb_struct_traits.cc", + "//components/services/leveldb/leveldb_struct_traits.cc", ] deps = [] public_deps = [
diff --git a/components/leveldb/leveldb_app.cc b/components/services/leveldb/leveldb_app.cc similarity index 90% rename from components/leveldb/leveldb_app.cc rename to components/services/leveldb/leveldb_app.cc index 76b48b3..fb98c44 100644 --- a/components/leveldb/leveldb_app.cc +++ b/components/services/leveldb/leveldb_app.cc
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/leveldb/leveldb_app.h" +#include "components/services/leveldb/leveldb_app.h" #include "base/task_scheduler/post_task.h" -#include "components/leveldb/leveldb_service_impl.h" +#include "components/services/leveldb/leveldb_service_impl.h" #include "services/service_manager/public/cpp/service_context.h" namespace leveldb {
diff --git a/components/leveldb/leveldb_app.h b/components/services/leveldb/leveldb_app.h similarity index 83% rename from components/leveldb/leveldb_app.h rename to components/services/leveldb/leveldb_app.h index f5696a3..06c1b87 100644 --- a/components/leveldb/leveldb_app.h +++ b/components/services/leveldb/leveldb_app.h
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_LEVELDB_LEVELDB_APP_H_ -#define COMPONENTS_LEVELDB_LEVELDB_APP_H_ +#ifndef COMPONENTS_SERVICES_LEVELDB_LEVELDB_APP_H_ +#define COMPONENTS_SERVICES_LEVELDB_LEVELDB_APP_H_ #include <memory> -#include "components/leveldb/public/interfaces/leveldb.mojom.h" +#include "components/services/leveldb/public/interfaces/leveldb.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/service.h" @@ -43,4 +43,4 @@ } // namespace leveldb -#endif // COMPONENTS_LEVELDB_LEVELDB_APP_H_ +#endif // COMPONENTS_SERVICES_LEVELDB_LEVELDB_APP_H_
diff --git a/components/leveldb/leveldb_database_impl.cc b/components/services/leveldb/leveldb_database_impl.cc similarity index 98% rename from components/leveldb/leveldb_database_impl.cc rename to components/services/leveldb/leveldb_database_impl.cc index f285c92..15be4ec5 100644 --- a/components/leveldb/leveldb_database_impl.cc +++ b/components/services/leveldb/leveldb_database_impl.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/leveldb/leveldb_database_impl.h" +#include "components/services/leveldb/leveldb_database_impl.h" #include <inttypes.h> #include <algorithm> @@ -15,8 +15,8 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/trace_event/memory_dump_manager.h" -#include "components/leveldb/env_mojo.h" -#include "components/leveldb/public/cpp/util.h" +#include "components/services/leveldb/env_mojo.h" +#include "components/services/leveldb/public/cpp/util.h" #include "third_party/leveldatabase/env_chromium.h" #include "third_party/leveldatabase/src/include/leveldb/db.h" #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
diff --git a/components/leveldb/leveldb_database_impl.h b/components/services/leveldb/leveldb_database_impl.h similarity index 94% rename from components/leveldb/leveldb_database_impl.h rename to components/services/leveldb/leveldb_database_impl.h index 757c61e1..8a11405 100644 --- a/components/leveldb/leveldb_database_impl.h +++ b/components/services/leveldb/leveldb_database_impl.h
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_LEVELDB_LEVELDB_DATABASE_IMPL_H_ -#define COMPONENTS_LEVELDB_LEVELDB_DATABASE_IMPL_H_ +#ifndef COMPONENTS_SERVICES_LEVELDB_LEVELDB_DATABASE_IMPL_H_ +#define COMPONENTS_SERVICES_LEVELDB_LEVELDB_DATABASE_IMPL_H_ #include <memory> #include <vector> #include "base/trace_event/memory_dump_provider.h" #include "base/unguessable_token.h" -#include "components/leveldb/public/interfaces/leveldb.mojom.h" +#include "components/services/leveldb/public/interfaces/leveldb.mojom.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "third_party/leveldatabase/src/include/leveldb/cache.h" #include "third_party/leveldatabase/src/include/leveldb/db.h" @@ -104,4 +104,4 @@ } // namespace leveldb -#endif // COMPONENTS_LEVELDB_LEVELDB_DATABASE_IMPL_H_ +#endif // COMPONENTS_SERVICES_LEVELDB_LEVELDB_DATABASE_IMPL_H_
diff --git a/components/leveldb/leveldb_mojo_proxy.cc b/components/services/leveldb/leveldb_mojo_proxy.cc similarity index 92% rename from components/leveldb/leveldb_mojo_proxy.cc rename to components/services/leveldb/leveldb_mojo_proxy.cc index c067719c..5ff7895 100644 --- a/components/leveldb/leveldb_mojo_proxy.cc +++ b/components/services/leveldb/leveldb_mojo_proxy.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/leveldb/leveldb_mojo_proxy.h" +#include "components/services/leveldb/leveldb_mojo_proxy.h" #include <set> @@ -37,38 +37,37 @@ filesystem::mojom::DirectoryPtr directory) { OpaqueDir* out_dir = nullptr; RunInternal(base::Bind(&LevelDBMojoProxy::RegisterDirectoryImpl, this, - base::Passed(directory.PassInterface()), - &out_dir)); + base::Passed(directory.PassInterface()), &out_dir)); return out_dir; } void LevelDBMojoProxy::UnregisterDirectory(OpaqueDir* dir) { - RunInternal(base::Bind(&LevelDBMojoProxy::UnregisterDirectoryImpl, - this, dir)); + RunInternal( + base::Bind(&LevelDBMojoProxy::UnregisterDirectoryImpl, this, dir)); } base::File LevelDBMojoProxy::OpenFileHandle(OpaqueDir* dir, const std::string& name, uint32_t open_flags) { base::File file; - RunInternal(base::Bind(&LevelDBMojoProxy::OpenFileHandleImpl, this, dir, - name, open_flags, &file)); + RunInternal(base::Bind(&LevelDBMojoProxy::OpenFileHandleImpl, this, dir, name, + open_flags, &file)); return file; } base::File::Error LevelDBMojoProxy::SyncDirectory(OpaqueDir* dir, const std::string& name) { base::File::Error error = base::File::Error::FILE_ERROR_FAILED; - RunInternal(base::Bind(&LevelDBMojoProxy::SyncDirectoryImpl, this, dir, - name, &error)); + RunInternal(base::Bind(&LevelDBMojoProxy::SyncDirectoryImpl, this, dir, name, + &error)); return error; } bool LevelDBMojoProxy::FileExists(OpaqueDir* dir, const std::string& name) { bool exists = false; - RunInternal(base::Bind(&LevelDBMojoProxy::FileExistsImpl, this, dir, - name, &exists)); + RunInternal( + base::Bind(&LevelDBMojoProxy::FileExistsImpl, this, dir, name, &exists)); return exists; } @@ -77,8 +76,8 @@ const std::string& path, std::vector<std::string>* result) { base::File::Error error = base::File::Error::FILE_ERROR_FAILED; - RunInternal(base::Bind(&LevelDBMojoProxy::GetChildrenImpl, this, dir, - path, result, &error)); + RunInternal(base::Bind(&LevelDBMojoProxy::GetChildrenImpl, this, dir, path, + result, &error)); return error; } @@ -94,8 +93,8 @@ base::File::Error LevelDBMojoProxy::CreateDir(OpaqueDir* dir, const std::string& path) { base::File::Error error = base::File::Error::FILE_ERROR_FAILED; - RunInternal(base::Bind(&LevelDBMojoProxy::CreateDirImpl, this, dir, path, - &error)); + RunInternal( + base::Bind(&LevelDBMojoProxy::CreateDirImpl, this, dir, path, &error)); return error; } @@ -103,8 +102,8 @@ const std::string& path, uint64_t* file_size) { base::File::Error error = base::File::Error::FILE_ERROR_FAILED; - RunInternal(base::Bind(&LevelDBMojoProxy::GetFileSizeImpl, this, dir, - path, file_size, &error)); + RunInternal(base::Bind(&LevelDBMojoProxy::GetFileSizeImpl, this, dir, path, + file_size, &error)); return error; } @@ -112,8 +111,8 @@ const std::string& old_path, const std::string& new_path) { base::File::Error error = base::File::Error::FILE_ERROR_FAILED; - RunInternal(base::Bind(&LevelDBMojoProxy::RenameFileImpl, this, dir, - old_path, new_path, &error)); + RunInternal(base::Bind(&LevelDBMojoProxy::RenameFileImpl, this, dir, old_path, + new_path, &error)); return error; } @@ -147,11 +146,8 @@ base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED); task_runner_->PostTask( - FROM_HERE, - base::Bind(&LevelDBMojoProxy::DoOnOtherThread, - this, - task, - base::Unretained(&done_event))); + FROM_HERE, base::Bind(&LevelDBMojoProxy::DoOnOtherThread, this, task, + base::Unretained(&done_event))); base::ScopedAllowBaseSyncPrimitives allow_base_sync_primitives; done_event.Wait(); } @@ -171,8 +167,7 @@ outstanding_opaque_dirs_++; } -void LevelDBMojoProxy::UnregisterDirectoryImpl( - OpaqueDir* dir) { +void LevelDBMojoProxy::UnregisterDirectoryImpl(OpaqueDir* dir) { // Only delete the directories on the thread that owns them. delete dir; outstanding_opaque_dirs_--;
diff --git a/components/leveldb/leveldb_mojo_proxy.h b/components/services/leveldb/leveldb_mojo_proxy.h similarity index 94% rename from components/leveldb/leveldb_mojo_proxy.h rename to components/services/leveldb/leveldb_mojo_proxy.h index eee605f4b..0ced74a 100644 --- a/components/leveldb/leveldb_mojo_proxy.h +++ b/components/services/leveldb/leveldb_mojo_proxy.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_LEVELDB_LEVELDB_MOJO_PROXY_H_ -#define COMPONENTS_LEVELDB_LEVELDB_MOJO_PROXY_H_ +#ifndef COMPONENTS_SERVICES_LEVELDB_LEVELDB_MOJO_PROXY_H_ +#define COMPONENTS_SERVICES_LEVELDB_LEVELDB_MOJO_PROXY_H_ #include <map> #include <memory> @@ -17,7 +17,7 @@ #include "base/sequenced_task_runner.h" #include "base/synchronization/waitable_event.h" -#include "components/filesystem/public/interfaces/directory.mojom.h" +#include "components/services/filesystem/public/interfaces/directory.mojom.h" namespace leveldb { @@ -118,9 +118,7 @@ void SyncDirectoryImpl(OpaqueDir* dir, std::string name, base::File::Error* out_error); - void FileExistsImpl(OpaqueDir* dir, - std::string name, - bool* exists); + void FileExistsImpl(OpaqueDir* dir, std::string name, bool* exists); void GetChildrenImpl(OpaqueDir* dir, std::string name, std::vector<std::string>* contents, @@ -158,4 +156,4 @@ } // namespace leveldb -#endif // COMPONENTS_LEVELDB_LEVELDB_MOJO_PROXY_H_ +#endif // COMPONENTS_SERVICES_LEVELDB_LEVELDB_MOJO_PROXY_H_
diff --git a/components/leveldb/leveldb_mojo_unittest.cc b/components/services/leveldb/leveldb_mojo_unittest.cc similarity index 95% rename from components/leveldb/leveldb_mojo_unittest.cc rename to components/services/leveldb/leveldb_mojo_unittest.cc index 490fd92..a9cf1f19 100644 --- a/components/leveldb/leveldb_mojo_unittest.cc +++ b/components/services/leveldb/leveldb_mojo_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -#include "components/leveldb/leveldb_struct_traits.h" +#include "components/services/leveldb/leveldb_struct_traits.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/leveldatabase/leveldb_chrome.h"
diff --git a/components/leveldb/leveldb_service_impl.cc b/components/services/leveldb/leveldb_service_impl.cc similarity index 94% rename from components/leveldb/leveldb_service_impl.cc rename to components/services/leveldb/leveldb_service_impl.cc index 639c38f9..7e4c6128 100644 --- a/components/leveldb/leveldb_service_impl.cc +++ b/components/services/leveldb/leveldb_service_impl.cc
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/leveldb/leveldb_service_impl.h" +#include "components/services/leveldb/leveldb_service_impl.h" #include <memory> #include <utility> -#include "components/leveldb/env_mojo.h" -#include "components/leveldb/leveldb_database_impl.h" -#include "components/leveldb/public/cpp/util.h" +#include "components/services/leveldb/env_mojo.h" +#include "components/services/leveldb/leveldb_database_impl.h" +#include "components/services/leveldb/public/cpp/util.h" #include "mojo/public/cpp/bindings/strong_associated_binding.h" #include "third_party/leveldatabase/leveldb_chrome.h" #include "third_party/leveldatabase/src/include/leveldb/db.h"
diff --git a/components/leveldb/leveldb_service_impl.h b/components/services/leveldb/leveldb_service_impl.h similarity index 87% rename from components/leveldb/leveldb_service_impl.h rename to components/services/leveldb/leveldb_service_impl.h index bae33e8..8eb0ebf7 100644 --- a/components/leveldb/leveldb_service_impl.h +++ b/components/services/leveldb/leveldb_service_impl.h
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_LEVELDB_LEVELDB_SERVICE_IMPL_H_ -#define COMPONENTS_LEVELDB_LEVELDB_SERVICE_IMPL_H_ +#ifndef COMPONENTS_SERVICES_LEVELDB_LEVELDB_SERVICE_IMPL_H_ +#define COMPONENTS_SERVICES_LEVELDB_LEVELDB_SERVICE_IMPL_H_ #include "base/memory/ref_counted.h" -#include "components/leveldb/leveldb_mojo_proxy.h" -#include "components/leveldb/public/interfaces/leveldb.mojom.h" +#include "components/services/leveldb/leveldb_mojo_proxy.h" +#include "components/services/leveldb/public/interfaces/leveldb.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" namespace base { @@ -60,4 +60,4 @@ } // namespace leveldb -#endif // COMPONENTS_LEVELDB_LEVELDB_SERVICE_IMPL_H_ +#endif // COMPONENTS_SERVICES_LEVELDB_LEVELDB_SERVICE_IMPL_H_
diff --git a/components/leveldb/leveldb_service_unittest.cc b/components/services/leveldb/leveldb_service_unittest.cc similarity index 98% rename from components/leveldb/leveldb_service_unittest.cc rename to components/services/leveldb/leveldb_service_unittest.cc index f18a375b8..514144e 100644 --- a/components/leveldb/leveldb_service_unittest.cc +++ b/components/services/leveldb/leveldb_service_unittest.cc
@@ -5,11 +5,11 @@ #include "base/bind.h" #include "base/macros.h" #include "base/run_loop.h" -#include "components/filesystem/public/interfaces/directory.mojom.h" -#include "components/filesystem/public/interfaces/file_system.mojom.h" -#include "components/filesystem/public/interfaces/types.mojom.h" -#include "components/leveldb/public/cpp/util.h" -#include "components/leveldb/public/interfaces/leveldb.mojom.h" +#include "components/services/filesystem/public/interfaces/directory.mojom.h" +#include "components/services/filesystem/public/interfaces/file_system.mojom.h" +#include "components/services/filesystem/public/interfaces/types.mojom.h" +#include "components/services/leveldb/public/cpp/util.h" +#include "components/services/leveldb/public/interfaces/leveldb.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/service_manager/public/cpp/service_context.h" #include "services/service_manager/public/cpp/service_test.h" @@ -17,7 +17,8 @@ namespace leveldb { namespace { -template <typename... Args> void IgnoreAllArgs(Args&&...) {} +template <typename... Args> +void IgnoreAllArgs(Args&&...) {} template <typename... Args> void DoCaptures(typename std::decay<Args>::type*... out_args,
diff --git a/components/leveldb/leveldb_struct_traits.cc b/components/services/leveldb/leveldb_struct_traits.cc similarity index 97% rename from components/leveldb/leveldb_struct_traits.cc rename to components/services/leveldb/leveldb_struct_traits.cc index 866f4d6d..bf720e6 100644 --- a/components/leveldb/leveldb_struct_traits.cc +++ b/components/services/leveldb/leveldb_struct_traits.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/leveldb/leveldb_struct_traits.h" +#include "components/services/leveldb/leveldb_struct_traits.h" #include "third_party/leveldatabase/env_chromium.h" #include "third_party/leveldatabase/leveldb_chrome.h"
diff --git a/components/leveldb/leveldb_struct_traits.h b/components/services/leveldb/leveldb_struct_traits.h similarity index 77% rename from components/leveldb/leveldb_struct_traits.h rename to components/services/leveldb/leveldb_struct_traits.h index 94221096..2d78836 100644 --- a/components/leveldb/leveldb_struct_traits.h +++ b/components/services/leveldb/leveldb_struct_traits.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_LEVELDB_LEVELDB_STRUCT_TRAITS_H_ -#define COMPONENTS_LEVELDB_LEVELDB_STRUCT_TRAITS_H_ +#ifndef COMPONENTS_SERVICES_LEVELDB_LEVELDB_STRUCT_TRAITS_H_ +#define COMPONENTS_SERVICES_LEVELDB_LEVELDB_STRUCT_TRAITS_H_ -#include "components/leveldb/public/interfaces/leveldb.mojom.h" +#include "components/services/leveldb/public/interfaces/leveldb.mojom.h" namespace mojo { @@ -24,4 +24,4 @@ } // namespace mojo -#endif // COMPONENTS_LEVELDB_LEVELDB_STRUCT_TRAITS_H_ +#endif // COMPONENTS_SERVICES_LEVELDB_LEVELDB_STRUCT_TRAITS_H_
diff --git a/components/leveldb/main.cc b/components/services/leveldb/main.cc similarity index 89% rename from components/leveldb/main.cc rename to components/services/leveldb/main.cc index 82ad845..6733f1ae 100644 --- a/components/leveldb/main.cc +++ b/components/services/leveldb/main.cc
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/macros.h" -#include "components/leveldb/leveldb_app.h" #include "services/service_manager/public/c/main.h" +#include "base/macros.h" +#include "components/services/leveldb/leveldb_app.h" #include "services/service_manager/public/cpp/service_runner.h" MojoResult ServiceMain(MojoHandle application_request) {
diff --git a/components/leveldb/manifest.json b/components/services/leveldb/manifest.json similarity index 100% rename from components/leveldb/manifest.json rename to components/services/leveldb/manifest.json
diff --git a/components/leveldb/public/cpp/BUILD.gn b/components/services/leveldb/public/cpp/BUILD.gn similarity index 88% rename from components/leveldb/public/cpp/BUILD.gn rename to components/services/leveldb/public/cpp/BUILD.gn index c729f4c..b43e96d8 100644 --- a/components/leveldb/public/cpp/BUILD.gn +++ b/components/services/leveldb/public/cpp/BUILD.gn
@@ -12,7 +12,7 @@ deps = [ "//base", - "//components/leveldb/public/interfaces", + "//components/services/leveldb/public/interfaces", "//mojo/common", "//services/service_manager/public/cpp", "//third_party/leveldatabase",
diff --git a/components/leveldb/public/cpp/remote_iterator.cc b/components/services/leveldb/public/cpp/remote_iterator.cc similarity index 92% rename from components/leveldb/public/cpp/remote_iterator.cc rename to components/services/leveldb/public/cpp/remote_iterator.cc index 089928a..0f9b5996 100644 --- a/components/leveldb/public/cpp/remote_iterator.cc +++ b/components/services/leveldb/public/cpp/remote_iterator.cc
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/leveldb/public/cpp/remote_iterator.h" +#include "components/services/leveldb/public/cpp/remote_iterator.h" -#include "components/leveldb/public/cpp/util.h" +#include "components/services/leveldb/public/cpp/util.h" namespace leveldb {
diff --git a/components/leveldb/public/cpp/remote_iterator.h b/components/services/leveldb/public/cpp/remote_iterator.h similarity index 82% rename from components/leveldb/public/cpp/remote_iterator.h rename to components/services/leveldb/public/cpp/remote_iterator.h index 41d2940..723e608 100644 --- a/components/leveldb/public/cpp/remote_iterator.h +++ b/components/services/leveldb/public/cpp/remote_iterator.h
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_LEVELDB_PUBLIC_CPP_REMOTE_ITERATOR_H_ -#define COMPONENTS_LEVELDB_PUBLIC_CPP_REMOTE_ITERATOR_H_ +#ifndef COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_REMOTE_ITERATOR_H_ +#define COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_REMOTE_ITERATOR_H_ #include "base/unguessable_token.h" -#include "components/leveldb/public/interfaces/leveldb.mojom.h" +#include "components/services/leveldb/public/interfaces/leveldb.mojom.h" #include "third_party/leveldatabase/src/include/leveldb/iterator.h" namespace leveldb { @@ -46,4 +46,4 @@ } // namespace leveldb -#endif // COMPONENTS_LEVELDB_PUBLIC_CPP_REMOTE_ITERATOR_H_ +#endif // COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_REMOTE_ITERATOR_H_
diff --git a/components/leveldb/public/cpp/util.cc b/components/services/leveldb/public/cpp/util.cc similarity index 98% rename from components/leveldb/public/cpp/util.cc rename to components/services/leveldb/public/cpp/util.cc index d20044d..63c36bd1 100644 --- a/components/leveldb/public/cpp/util.cc +++ b/components/services/leveldb/public/cpp/util.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/leveldb/public/cpp/util.h" +#include "components/services/leveldb/public/cpp/util.h" #include "third_party/leveldatabase/env_chromium.h" #include "third_party/leveldatabase/src/include/leveldb/status.h"
diff --git a/components/leveldb/public/cpp/util.h b/components/services/leveldb/public/cpp/util.h similarity index 85% rename from components/leveldb/public/cpp/util.h rename to components/services/leveldb/public/cpp/util.h index 4a5618f..9c1a718 100644 --- a/components/leveldb/public/cpp/util.h +++ b/components/services/leveldb/public/cpp/util.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_LEVELDB_PUBLIC_CPP_UTIL_H_ -#define COMPONENTS_LEVELDB_PUBLIC_CPP_UTIL_H_ +#ifndef COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_UTIL_H_ +#define COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_UTIL_H_ -#include "components/leveldb/public/interfaces/leveldb.mojom.h" +#include "components/services/leveldb/public/interfaces/leveldb.mojom.h" #include "third_party/leveldatabase/env_chromium.h" namespace leveldb { @@ -41,4 +41,4 @@ } // namespace leveldb -#endif // COMPONENTS_LEVELDB_PUBLIC_CPP_UTIL_H_ +#endif // COMPONENTS_SERVICES_LEVELDB_PUBLIC_CPP_UTIL_H_
diff --git a/components/leveldb/public/interfaces/BUILD.gn b/components/services/leveldb/public/interfaces/BUILD.gn similarity index 86% rename from components/leveldb/public/interfaces/BUILD.gn rename to components/services/leveldb/public/interfaces/BUILD.gn index 1b3172e6..4e519e6 100644 --- a/components/leveldb/public/interfaces/BUILD.gn +++ b/components/services/leveldb/public/interfaces/BUILD.gn
@@ -12,7 +12,7 @@ ] deps = [ - "//components/filesystem/public/interfaces", + "//components/services/filesystem/public/interfaces", ] public_deps = [
diff --git a/components/leveldb/public/interfaces/OWNERS b/components/services/leveldb/public/interfaces/OWNERS similarity index 100% rename from components/leveldb/public/interfaces/OWNERS rename to components/services/leveldb/public/interfaces/OWNERS
diff --git a/components/leveldb/public/interfaces/leveldb.mojom b/components/services/leveldb/public/interfaces/leveldb.mojom similarity index 98% rename from components/leveldb/public/interfaces/leveldb.mojom rename to components/services/leveldb/public/interfaces/leveldb.mojom index 1dcca48..a4144f600 100644 --- a/components/leveldb/public/interfaces/leveldb.mojom +++ b/components/services/leveldb/public/interfaces/leveldb.mojom
@@ -4,7 +4,7 @@ module leveldb.mojom; -import "components/filesystem/public/interfaces/directory.mojom"; +import "components/services/filesystem/public/interfaces/directory.mojom"; import "mojo/common/unguessable_token.mojom"; import "mojo/common/memory_allocator_dump_cross_process_uid.mojom";
diff --git a/components/leveldb/remote_iterator_unittest.cc b/components/services/leveldb/remote_iterator_unittest.cc similarity index 95% rename from components/leveldb/remote_iterator_unittest.cc rename to components/services/leveldb/remote_iterator_unittest.cc index f37bd48..e763736 100644 --- a/components/leveldb/remote_iterator_unittest.cc +++ b/components/services/leveldb/remote_iterator_unittest.cc
@@ -7,9 +7,9 @@ #include "base/bind.h" #include "base/macros.h" #include "base/run_loop.h" -#include "components/leveldb/public/cpp/remote_iterator.h" -#include "components/leveldb/public/cpp/util.h" -#include "components/leveldb/public/interfaces/leveldb.mojom.h" +#include "components/services/leveldb/public/cpp/remote_iterator.h" +#include "components/services/leveldb/public/cpp/util.h" +#include "components/services/leveldb/public/interfaces/leveldb.mojom.h" #include "services/service_manager/public/cpp/service_context.h" #include "services/service_manager/public/cpp/service_test.h"
diff --git a/components/leveldb/test_manifest.json b/components/services/leveldb/test_manifest.json similarity index 100% rename from components/leveldb/test_manifest.json rename to components/services/leveldb/test_manifest.json
diff --git a/components/typemaps.gni b/components/typemaps.gni index f8256636..f53c803 100644 --- a/components/typemaps.gni +++ b/components/typemaps.gni
@@ -6,7 +6,7 @@ "//components/autofill/content/common/autofill_types.typemap", "//components/chrome_cleaner/public/typemaps/chrome_prompt.typemap", "//components/content_settings/core/common/content_settings.typemap", - "//components/leveldb/leveldb.typemap", + "//components/services/leveldb/leveldb.typemap", "//components/nacl/common/nacl.typemap", "//components/password_manager/content/common/credential_manager.typemap", "//components/password_manager/public/interfaces/sync_password_data.typemap",
diff --git a/components/unzip_service/BUILD.gn b/components/unzip_service/BUILD.gn index 67252b0..a5fcf20 100644 --- a/components/unzip_service/BUILD.gn +++ b/components/unzip_service/BUILD.gn
@@ -20,7 +20,7 @@ ] public_deps = [ - "//components/filesystem/public/interfaces", + "//components/services/filesystem/public/interfaces", "//components/unzip_service/public/interfaces", "//services/service_manager/public/cpp", ]
diff --git a/components/unzip_service/DEPS b/components/unzip_service/DEPS index 116747a..9a39d2d 100644 --- a/components/unzip_service/DEPS +++ b/components/unzip_service/DEPS
@@ -1,5 +1,5 @@ include_rules = [ - "+components/filesystem", + "+components/services/filesystem", "+mojo/public", "+services/service_manager/public", "+third_party/zlib/google",
diff --git a/components/unzip_service/public/cpp/BUILD.gn b/components/unzip_service/public/cpp/BUILD.gn index a11aebd..738158d 100644 --- a/components/unzip_service/public/cpp/BUILD.gn +++ b/components/unzip_service/public/cpp/BUILD.gn
@@ -11,7 +11,7 @@ ] public_deps = [ - "//components/filesystem:lib", + "//components/services/filesystem:lib", "//components/unzip_service/public/interfaces", "//services/service_manager/public/cpp", ]
diff --git a/components/unzip_service/public/cpp/unzip.cc b/components/unzip_service/public/cpp/unzip.cc index a8ab1f5..35480fa3 100644 --- a/components/unzip_service/public/cpp/unzip.cc +++ b/components/unzip_service/public/cpp/unzip.cc
@@ -16,8 +16,8 @@ #include "base/strings/string16.h" #include "base/task_scheduler/post_task.h" #include "base/threading/sequenced_task_runner_handle.h" -#include "components/filesystem/directory_impl.h" -#include "components/filesystem/lock_table.h" +#include "components/services/filesystem/directory_impl.h" +#include "components/services/filesystem/lock_table.h" #include "components/unzip_service/public/interfaces/constants.mojom.h" #include "components/unzip_service/public/interfaces/unzipper.mojom.h" #include "mojo/public/cpp/bindings/strong_binding.h"
diff --git a/components/unzip_service/public/interfaces/BUILD.gn b/components/unzip_service/public/interfaces/BUILD.gn index d048a589..1fc91bd2 100644 --- a/components/unzip_service/public/interfaces/BUILD.gn +++ b/components/unzip_service/public/interfaces/BUILD.gn
@@ -11,7 +11,7 @@ public_deps = [ ":constants", - "//components/filesystem/public/interfaces", + "//components/services/filesystem/public/interfaces", "//mojo/common:common_custom_types", ] }
diff --git a/components/unzip_service/public/interfaces/unzipper.mojom b/components/unzip_service/public/interfaces/unzipper.mojom index f8164700..77790e5 100644 --- a/components/unzip_service/public/interfaces/unzipper.mojom +++ b/components/unzip_service/public/interfaces/unzipper.mojom
@@ -6,7 +6,7 @@ import "mojo/common/file.mojom"; import "mojo/common/file_path.mojom"; -import "components/filesystem/public/interfaces/directory.mojom"; +import "components/services/filesystem/public/interfaces/directory.mojom"; interface UnzipFilter { [Sync]
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 7992ec8..78ab406a 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -48,8 +48,6 @@ "//components/download/public/common:public", "//components/download/quarantine", "//components/filename_generation", - "//components/filesystem:lib", - "//components/leveldb:lib", "//components/link_header_util", "//components/metrics", "//components/metrics:single_sample_metrics", @@ -57,6 +55,8 @@ "//components/offline_pages/buildflags", "//components/offline_pages/core/request_header", "//components/rappor", + "//components/services/filesystem:lib", + "//components/services/leveldb:lib", "//components/tracing", "//components/tracing:startup_tracing", "//components/url_formatter",
diff --git a/content/browser/DEPS b/content/browser/DEPS index 1679126..4ed4529 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS
@@ -7,8 +7,8 @@ "+components/download/public/common", "+components/download/quarantine/quarantine.h", "+components/filename_generation", - "+components/filesystem", - "+components/leveldb", + "+components/services/filesystem", + "+components/services/leveldb", "+components/link_header_util", "+components/metrics", "+components/metrics:single_sample_metrics",
diff --git a/content/browser/accessibility/aom_browsertest.cc b/content/browser/accessibility/aom_browsertest.cc new file mode 100644 index 0000000..0a614f8 --- /dev/null +++ b/content/browser/accessibility/aom_browsertest.cc
@@ -0,0 +1,97 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/logging.h" +#include "content/browser/accessibility/browser_accessibility.h" +#include "content/browser/accessibility/browser_accessibility_manager.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/common/content_switches.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/content_browser_test.h" +#include "content/public/test/content_browser_test_utils.h" +#include "content/public/test/test_utils.h" +#include "content/shell/browser/shell.h" +#include "content/test/accessibility_browser_test_utils.h" +#include "net/base/data_url.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace content { + +namespace { + +class AccessibilityObjectModelBrowserTest : public ContentBrowserTest { + public: + AccessibilityObjectModelBrowserTest() {} + ~AccessibilityObjectModelBrowserTest() override {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + ContentBrowserTest::SetUpCommandLine(command_line); + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kEnableBlinkFeatures, "AccessibilityObjectModel"); + } + + protected: + BrowserAccessibility* FindNode(ax::mojom::Role role, + const std::string& name) { + BrowserAccessibility* root = GetManager()->GetRoot(); + CHECK(root); + return FindNodeInSubtree(*root, role, name); + } + + BrowserAccessibilityManager* GetManager() { + WebContentsImpl* web_contents = + static_cast<WebContentsImpl*>(shell()->web_contents()); + return web_contents->GetRootBrowserAccessibilityManager(); + } + + private: + BrowserAccessibility* FindNodeInSubtree(BrowserAccessibility& node, + ax::mojom::Role role, + const std::string& name) { + if (node.GetRole() == role && + node.GetStringAttribute(ax::mojom::StringAttribute::kName) == name) + return &node; + for (unsigned int i = 0; i < node.PlatformChildCount(); ++i) { + BrowserAccessibility* result = + FindNodeInSubtree(*node.PlatformGetChild(i), role, name); + if (result) + return result; + } + return nullptr; + } +}; + +} // namespace + +IN_PROC_BROWSER_TEST_F(AccessibilityObjectModelBrowserTest, + EventListenerOnVirtualNode) { + ASSERT_TRUE(embedded_test_server()->Start()); + NavigateToURL(shell(), GURL(url::kAboutBlankURL)); + + AccessibilityNotificationWaiter waiter(shell()->web_contents(), + ui::kAXModeComplete, + ax::mojom::Event::kLoadComplete); + GURL url(embedded_test_server()->GetURL( + "/accessibility/aom/event-listener-on-virtual-node.html")); + NavigateToURL(shell(), url); + waiter.WaitForNotification(); + + BrowserAccessibility* button = FindNode(ax::mojom::Role::kButton, "FocusMe"); + ASSERT_NE(nullptr, button); + + BrowserAccessibility* link = FindNode(ax::mojom::Role::kLink, "ClickMe"); + ASSERT_NE(nullptr, link); + + AccessibilityNotificationWaiter waiter2( + shell()->web_contents(), ui::kAXModeComplete, ax::mojom::Event::kFocus); + GetManager()->DoDefaultAction(*link); + waiter2.WaitForNotification(); + + BrowserAccessibility* focus = GetManager()->GetFocus(); + EXPECT_EQ(focus->GetId(), button->GetId()); +} + +} // namespace content
diff --git a/content/browser/dom_storage/local_storage_context_mojo.cc b/content/browser/dom_storage/local_storage_context_mojo.cc index 4a88ace..53e38c9d1 100644 --- a/content/browser/dom_storage/local_storage_context_mojo.cc +++ b/content/browser/dom_storage/local_storage_context_mojo.cc
@@ -22,8 +22,8 @@ #include "base/sys_info.h" #include "base/trace_event/memory_dump_manager.h" #include "build/build_config.h" -#include "components/leveldb/public/cpp/util.h" -#include "components/leveldb/public/interfaces/leveldb.mojom.h" +#include "components/services/leveldb/public/cpp/util.h" +#include "components/services/leveldb/public/interfaces/leveldb.mojom.h" #include "content/browser/dom_storage/dom_storage_area.h" #include "content/browser/dom_storage/dom_storage_database.h" #include "content/browser/dom_storage/dom_storage_task_runner.h"
diff --git a/content/browser/dom_storage/local_storage_context_mojo_unittest.cc b/content/browser/dom_storage/local_storage_context_mojo_unittest.cc index 4687ad5d4..1603bdb 100644 --- a/content/browser/dom_storage/local_storage_context_mojo_unittest.cc +++ b/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
@@ -11,8 +11,8 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "components/filesystem/public/interfaces/file_system.mojom.h" -#include "components/leveldb/public/cpp/util.h" +#include "components/services/filesystem/public/interfaces/file_system.mojom.h" +#include "components/services/leveldb/public/cpp/util.h" #include "content/browser/dom_storage/dom_storage_area.h" #include "content/browser/dom_storage/dom_storage_context_impl.h" #include "content/browser/dom_storage/dom_storage_database.h"
diff --git a/content/browser/leveldb_wrapper_impl.cc b/content/browser/leveldb_wrapper_impl.cc index d5173bf1..0ff7b32 100644 --- a/content/browser/leveldb_wrapper_impl.cc +++ b/content/browser/leveldb_wrapper_impl.cc
@@ -11,7 +11,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/process_memory_dump.h" -#include "components/leveldb/public/cpp/util.h" +#include "components/services/leveldb/public/cpp/util.h" #include "content/public/browser/browser_thread.h" namespace content {
diff --git a/content/browser/leveldb_wrapper_impl_unittest.cc b/content/browser/leveldb_wrapper_impl_unittest.cc index 59624ee1..5e63e99 100644 --- a/content/browser/leveldb_wrapper_impl_unittest.cc +++ b/content/browser/leveldb_wrapper_impl_unittest.cc
@@ -13,8 +13,8 @@ #include "base/task_scheduler/post_task.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/thread.h" -#include "components/leveldb/public/cpp/util.h" -#include "components/leveldb/public/interfaces/leveldb.mojom.h" +#include "components/services/leveldb/public/cpp/util.h" +#include "components/services/leveldb/public/interfaces/leveldb.mojom.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/test/fake_leveldb_database.h" #include "mojo/public/cpp/bindings/associated_binding.h"
diff --git a/content/browser/service_worker/service_worker_handle.cc b/content/browser/service_worker/service_worker_handle.cc index f73b082..0aee7f2 100644 --- a/content/browser/service_worker/service_worker_handle.cc +++ b/content/browser/service_worker/service_worker_handle.cc
@@ -175,6 +175,7 @@ : dispatcher_host_(dispatcher_host), context_(context), provider_host_(provider_host), + provider_origin_(url::Origin::Create(provider_host->document_url())), provider_id_(provider_host->provider_id()), handle_id_(context->GetNewServiceWorkerHandleId()), version_(version), @@ -222,16 +223,15 @@ dispatcher_host_->RegisterServiceWorkerHandle(base::WrapUnique(this)); } -void ServiceWorkerHandle::PostMessage(::blink::TransferableMessage message, - const url::Origin& source_origin) { +void ServiceWorkerHandle::PostMessageToServiceWorker( + ::blink::TransferableMessage message) { // When this method is called the encoded_message inside message could just // point to the IPC message's buffer. But that buffer can become invalid // before the message is passed on to the service worker, so make sure // message owns its data. message.EnsureDataIsOwned(); - DispatchExtendableMessageEvent(std::move(message), source_origin, - base::DoNothing()); + DispatchExtendableMessageEvent(std::move(message), base::DoNothing()); } void ServiceWorkerHandle::TerminateForTesting( @@ -241,18 +241,19 @@ void ServiceWorkerHandle::DispatchExtendableMessageEvent( ::blink::TransferableMessage message, - const url::Origin& source_origin, StatusCallback callback) { if (!context_ || !provider_host_) { std::move(callback).Run(SERVICE_WORKER_ERROR_FAILED); return; } + DCHECK_EQ(provider_origin_, + url::Origin::Create(provider_host_->document_url())); switch (provider_host_->provider_type()) { case blink::mojom::ServiceWorkerProviderType::kForWindow: service_worker_client_utils::GetClient( provider_host_.get(), base::BindOnce(&DispatchExtendableMessageEventFromClient, version_, - std::move(message), source_origin, + std::move(message), provider_origin_, std::move(callback))); return; case blink::mojom::ServiceWorkerProviderType::kForServiceWorker: { @@ -264,7 +265,7 @@ base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&DispatchExtendableMessageEventFromServiceWorker, - version_, std::move(message), source_origin, + version_, std::move(message), provider_origin_, base::make_optional(timeout), std::move(callback), provider_host_)); return;
diff --git a/content/browser/service_worker/service_worker_handle.h b/content/browser/service_worker/service_worker_handle.h index b5037d8..f9bfb06 100644 --- a/content/browser/service_worker/service_worker_handle.h +++ b/content/browser/service_worker/service_worker_handle.h
@@ -10,23 +10,12 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "build/build_config.h" #include "content/browser/service_worker/service_worker_version.h" #include "content/common/content_export.h" #include "content/common/service_worker/service_worker_types.h" #include "mojo/public/cpp/bindings/associated_binding_set.h" #include "third_party/WebKit/public/mojom/service_worker/service_worker_object.mojom.h" - -#if defined(OS_WIN) -// Since PostMessage is a Win32 macro, ensure that it has the same -// value every time this header is parsed. This avoids strange -// compilation and linking errors. -#include "base/win/windows_types.h" -#endif - -namespace url { -class Origin; -} // namespace url +#include "url/origin.h" namespace content { @@ -91,13 +80,15 @@ ServiceWorkerVersion* version); // Implements blink::mojom::ServiceWorkerObjectHost. - void PostMessage(::blink::TransferableMessage message, - const url::Origin& source_origin) override; + void PostMessageToServiceWorker( + ::blink::TransferableMessage message) override; void TerminateForTesting(TerminateForTestingCallback callback) override; + // TODO(leonhsl): Remove |callback| parameter because it's just for unit tests + // and production code does not use it. We need to figure out another way to + // observe the dispatch result in unit tests. void DispatchExtendableMessageEvent( ::blink::TransferableMessage message, - const url::Origin& source_origin, base::OnceCallback<void(ServiceWorkerStatusCode)> callback); base::WeakPtr<ServiceWorkerHandle> AsWeakPtr(); @@ -111,6 +102,11 @@ ServiceWorkerDispatcherHost* dispatcher_host_; base::WeakPtr<ServiceWorkerContextCore> context_; base::WeakPtr<ServiceWorkerProviderHost> provider_host_; + // The origin of the |provider_host_|. Note that this is const because once a + // JavaScript ServiceWorker object is created for an execution context, we + // don't expect that context to change origins and still hold on to the + // object. + const url::Origin provider_origin_; const int provider_id_; const int handle_id_; scoped_refptr<ServiceWorkerVersion> version_;
diff --git a/content/browser/service_worker/service_worker_handle_unittest.cc b/content/browser/service_worker/service_worker_handle_unittest.cc index 18f49d5..519152a 100644 --- a/content/browser/service_worker/service_worker_handle_unittest.cc +++ b/content/browser/service_worker/service_worker_handle_unittest.cc
@@ -183,9 +183,8 @@ void CallDispatchExtendableMessageEvent( ServiceWorkerHandle* handle, ::blink::TransferableMessage message, - const url::Origin& source_origin, base::OnceCallback<void(ServiceWorkerStatusCode)> callback) { - handle->DispatchExtendableMessageEvent(std::move(message), source_origin, + handle->DispatchExtendableMessageEvent(std::move(message), std::move(callback)); } @@ -302,7 +301,6 @@ status = SERVICE_WORKER_ERROR_MAX_VALUE; CallDispatchExtendableMessageEvent( sender_worker_handle.get(), std::move(message), - url::Origin::Create(version_->scope().GetOrigin()), base::BindOnce(&SaveStatusCallback, &called, &status)); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(called); @@ -349,6 +347,7 @@ ServiceWorkerProviderHost::Create( frame_host->GetProcess()->GetID(), std::move(provider_host_info), helper_->context()->AsWeakPtr(), dispatcher_host_->AsWeakPtr()); + provider_host->SetDocumentUrl(pattern); // Prepare a ServiceWorkerHandle for the above |provider_host|. blink::mojom::ServiceWorkerObjectInfoPtr info; // ServiceWorkerHandle lifetime is controlled by |info| and is also owned by @@ -364,7 +363,6 @@ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE; CallDispatchExtendableMessageEvent( handle.get(), std::move(message), - url::Origin::Create(version_->scope().GetOrigin()), base::BindOnce(&SaveStatusCallback, &called, &status)); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(called); @@ -406,6 +404,7 @@ ServiceWorkerProviderHost::Create( frame_host->GetProcess()->GetID(), std::move(provider_host_info), helper_->context()->AsWeakPtr(), dispatcher_host_->AsWeakPtr()); + provider_host->SetDocumentUrl(pattern); // Prepare a ServiceWorkerHandle for the above |provider_host|. blink::mojom::ServiceWorkerObjectInfoPtr info; // ServiceWorkerHandle lifetime is controlled by |info| and is also owned by @@ -422,7 +421,6 @@ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE; CallDispatchExtendableMessageEvent( handle.get(), std::move(message), - url::Origin::Create(version_->scope().GetOrigin()), base::BindOnce(&SaveStatusCallback, &called, &status)); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(called);
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc index 35ec729..e3838b8 100644 --- a/content/browser/service_worker/service_worker_provider_host.cc +++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -643,6 +643,7 @@ DCHECK(dispatcher_host); render_process_id_ = process_id; dispatcher_host_ = dispatcher_host->AsWeakPtr(); + SetDocumentUrl(running_hosted_version()->script_url()); // Retrieve the registration associated with |version|. The registration // must be alive because the version keeps it during starting worker. @@ -677,10 +678,6 @@ mojom::kNavigation_ServiceWorkerSpec, process_id, mojo::MakeRequest(&provider_info->interface_provider))); - // Set the document URL to the script url in order to allow - // register/unregister/getRegistration on ServiceWorkerGlobalScope. - SetDocumentUrl(running_hosted_version()->script_url()); - return provider_info; }
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h index fdbe5b5..3e0a0e7 100644 --- a/content/browser/service_worker/service_worker_provider_host.h +++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -232,6 +232,12 @@ // Sets the |document_url_|. When this object is for a client, // |matching_registrations_| gets also updated to ensure that |document_url_| // is in scope of all |matching_registrations_|. + // |document_url_| is the service worker script URL if this is hosting a + // running service worker, it will be used when creating ServiceWorkerHandle + // or handling ServiceWorkerRegistration#{*} calls etc. + // TODO(leonhsl): We should rename |document_url_| to something more + // appropriate and/or split this class into one for clients vs one for service + // workers. void SetDocumentUrl(const GURL& url); const GURL& document_url() const { return document_url_; }
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 6783df6a..a37840a 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -1120,6 +1120,10 @@ if (!provider_host || provider_host->document_url().GetOrigin() != script_url_.GetOrigin()) { // The promise will be resolved to 'undefined'. + // Note that we don't BadMessage here since Clients#get() can be passed an + // arbitrary UUID. The BadMessages for the origin mismatches below are + // appropriate because the UUID is taken directly from a Client object so we + // expect it to be valid. std::move(callback).Run(nullptr); return; } @@ -1166,15 +1170,16 @@ return; } if (provider_host->document_url().GetOrigin() != script_url_.GetOrigin()) { - // The client does not belong to the same origin as this ServiceWorker, - // possibly due to timing issue or bad message. - std::move(callback).Run(nullptr /* client */); + mojo::ReportBadMessage( + "Received WindowClient#focus() request for a cross-origin client."); + binding_.Close(); return; } if (provider_host->client_type() != blink::mojom::ServiceWorkerClientType::kWindow) { // focus() should be called only for WindowClient. - mojo::ReportBadMessage("Received focus() request for a non-window client."); + mojo::ReportBadMessage( + "Received WindowClient#focus() request for a non-window client."); binding_.Close(); return; } @@ -1219,6 +1224,20 @@ std::string("The client was not found.")); return; } + if (provider_host->document_url().GetOrigin() != script_url_.GetOrigin()) { + mojo::ReportBadMessage( + "Received WindowClient#navigate() request for a cross-origin client."); + binding_.Close(); + return; + } + if (provider_host->client_type() != + blink::mojom::ServiceWorkerClientType::kWindow) { + // navigate() should be called only for WindowClient. + mojo::ReportBadMessage( + "Received WindowClient#navigate() request for a non-window client."); + binding_.Close(); + return; + } if (provider_host->active_version() != this) { std::move(callback).Run( false /* success */, nullptr /* client */, @@ -1372,8 +1391,7 @@ message) { if (!context_) return; - TRACE_EVENT1("ServiceWorker", - "ServiceWorkerVersion::OnPostMessageToDocument", + TRACE_EVENT1("ServiceWorker", "ServiceWorkerVersion::OnPostMessageToClient", "Client id", client_uuid); ServiceWorkerProviderHost* provider_host = context_->GetProviderHostByClientID(client_uuid); @@ -1382,8 +1400,9 @@ return; } if (provider_host->document_url().GetOrigin() != script_url_.GetOrigin()) { - // The client does not belong to the same origin as this ServiceWorker, - // possibly due to timing issue or bad message. + mojo::ReportBadMessage( + "Received Client#postMessage() request for a cross-origin client."); + binding_.Close(); return; } provider_host->PostMessageToClient(this, std::move(message->data));
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc index cfb2f80..c856ca4 100644 --- a/content/browser/storage_partition_impl_unittest.cc +++ b/content/browser/storage_partition_impl_unittest.cc
@@ -13,7 +13,7 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" -#include "components/leveldb/public/cpp/util.h" +#include "components/services/leveldb/public/cpp/util.h" #include "content/browser/browser_thread_impl.h" #include "content/browser/dom_storage/local_storage_database.pb.h" #include "content/browser/gpu/shader_cache_factory.h"
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index da45e08a..330c1f7 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -254,10 +254,6 @@ base::FeatureList::IsEnabled( features::kFramebustingNeedsSameOriginOrUserGesture)); - WebRuntimeFeatures::EnableFeatureFromString( - "VibrateRequiresUserGesture", - base::FeatureList::IsEnabled(features::kVibrateRequiresUserGesture)); - if (command_line.HasSwitch(switches::kDisableBackgroundTimerThrottling)) WebRuntimeFeatures::EnableTimerThrottlingForBackgroundTabs(false);
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index 322e8736..0dde314c 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -608,7 +608,7 @@ import_dirs = [ "//mojo/services" ] public_deps = [ - "//components/leveldb/public/interfaces", + "//components/services/leveldb/public/interfaces", "//content/public/common:interfaces", "//content/public/common:resource_type_bindings", "//ipc:mojom_constants",
diff --git a/content/common/leveldb_wrapper.mojom b/content/common/leveldb_wrapper.mojom index 8640584e..4b03843 100644 --- a/content/common/leveldb_wrapper.mojom +++ b/content/common/leveldb_wrapper.mojom
@@ -4,7 +4,7 @@ module content.mojom; -import "components/leveldb/public/interfaces/leveldb.mojom"; +import "components/services/leveldb/public/interfaces/leveldb.mojom"; // Gives information about changes to a LevelDB database. // Note that observer methods are called before the callbacks for the
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index bbf8311..e390c3a 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -424,10 +424,6 @@ const base::Feature kV8VmFuture{"V8VmFuture", base::FEATURE_DISABLED_BY_DEFAULT}; -// Controls whether vibrate requires user gesture. -const base::Feature kVibrateRequiresUserGesture{ - "VibrateRequiresUserGesture", base::FEATURE_ENABLED_BY_DEFAULT}; - // Controls whether editing web input fields is enabled in VR. const base::Feature kVrWebInputEditing{"VrWebInputEditing", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index f115485..2c400ac 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -102,7 +102,6 @@ CONTENT_EXPORT extern const base::Feature kUserActivationV2; CONTENT_EXPORT extern const base::Feature kV8ContextSnapshot; CONTENT_EXPORT extern const base::Feature kV8VmFuture; -CONTENT_EXPORT extern const base::Feature kVibrateRequiresUserGesture; CONTENT_EXPORT extern const base::Feature kVrWebInputEditing; CONTENT_EXPORT extern const base::Feature kWebAssembly; CONTENT_EXPORT extern const base::Feature kWebAssemblyStreaming;
diff --git a/content/renderer/dom_storage/DEPS b/content/renderer/dom_storage/DEPS index b1259df..f57963b8 100644 --- a/content/renderer/dom_storage/DEPS +++ b/content/renderer/dom_storage/DEPS
@@ -1,7 +1,7 @@ specific_include_rules = { 'local_storage\.*': [ "-content/renderer", - "+components/leveldb/public/interfaces", + "+components/services/leveldb/public/interfaces", "+content/common/dom_storage/dom_storage_map.h", "+content/renderer/dom_storage/local_storage_cached_area.h", "+content/renderer/dom_storage/local_storage_cached_areas.h",
diff --git a/content/renderer/media/webrtc/rtc_certificate_generator.cc b/content/renderer/media/webrtc/rtc_certificate_generator.cc index 0c29b6de..3daabb6f 100644 --- a/content/renderer/media/webrtc/rtc_certificate_generator.cc +++ b/content/renderer/media/webrtc/rtc_certificate_generator.cc
@@ -93,7 +93,9 @@ FROM_HERE, base::BindOnce(&RTCCertificateGeneratorRequest::DoCallbackOnMainThread, this, std::move(observer), - std::make_unique<RTCCertificate>(certificate))); + certificate + ? std::make_unique<RTCCertificate>(certificate) + : nullptr)); } void DoCallbackOnMainThread(
diff --git a/content/renderer/service_worker/service_worker_dispatcher_unittest.cc b/content/renderer/service_worker/service_worker_dispatcher_unittest.cc index 372f41f..e30bc92 100644 --- a/content/renderer/service_worker/service_worker_dispatcher_unittest.cc +++ b/content/renderer/service_worker/service_worker_dispatcher_unittest.cc
@@ -38,8 +38,8 @@ private: // Implements blink::mojom::ServiceWorkerObjectHost. - void PostMessage(::blink::TransferableMessage message, - const url::Origin& source_origin) override { + void PostMessageToServiceWorker( + ::blink::TransferableMessage message) override { NOTREACHED(); } void TerminateForTesting(TerminateForTestingCallback callback) override {
diff --git a/content/renderer/service_worker/service_worker_provider_context_unittest.cc b/content/renderer/service_worker/service_worker_provider_context_unittest.cc index 2b769d32..6006ef77d 100644 --- a/content/renderer/service_worker/service_worker_provider_context_unittest.cc +++ b/content/renderer/service_worker/service_worker_provider_context_unittest.cc
@@ -61,8 +61,8 @@ private: // Implements blink::mojom::ServiceWorkerObjectHost. - void PostMessage(::blink::TransferableMessage message, - const url::Origin& source_origin) override { + void PostMessageToServiceWorker( + ::blink::TransferableMessage message) override { NOTREACHED(); } void TerminateForTesting(TerminateForTestingCallback callback) override {
diff --git a/content/renderer/service_worker/web_service_worker_impl.cc b/content/renderer/service_worker/web_service_worker_impl.cc index 94037ab..8217a951 100644 --- a/content/renderer/service_worker/web_service_worker_impl.cc +++ b/content/renderer/service_worker/web_service_worker_impl.cc
@@ -13,11 +13,9 @@ #include "content/renderer/service_worker/service_worker_dispatcher.h" #include "content/renderer/service_worker/web_service_worker_provider_impl.h" #include "third_party/WebKit/public/platform/WebRuntimeFeatures.h" -#include "third_party/WebKit/public/platform/WebSecurityOrigin.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProxy.h" -using blink::WebSecurityOrigin; using blink::WebString; namespace content { @@ -97,9 +95,9 @@ return state_; } -void WebServiceWorkerImpl::PostMessage(blink::TransferableMessage message, - const WebSecurityOrigin& source_origin) { - GetObjectHost()->PostMessage(std::move(message), url::Origin(source_origin)); +void WebServiceWorkerImpl::PostMessageToServiceWorker( + blink::TransferableMessage message) { + GetObjectHost()->PostMessageToServiceWorker(std::move(message)); } void WebServiceWorkerImpl::TerminateForTesting(
diff --git a/content/renderer/service_worker/web_service_worker_impl.h b/content/renderer/service_worker/web_service_worker_impl.h index 9368828..28036b3 100644 --- a/content/renderer/service_worker/web_service_worker_impl.h +++ b/content/renderer/service_worker/web_service_worker_impl.h
@@ -59,8 +59,7 @@ blink::WebServiceWorkerProxy* Proxy() override; blink::WebURL Url() const override; blink::mojom::ServiceWorkerState GetState() const override; - void PostMessage(blink::TransferableMessage message, - const blink::WebSecurityOrigin& source_origin) override; + void PostMessageToServiceWorker(blink::TransferableMessage message) override; void TerminateForTesting( std::unique_ptr<TerminateForTestingCallback> callback) override;
diff --git a/content/shell/browser/shell_permission_manager.cc b/content/shell/browser/shell_permission_manager.cc index b445d63d..25036ee 100644 --- a/content/shell/browser/shell_permission_manager.cc +++ b/content/shell/browser/shell_permission_manager.cc
@@ -25,7 +25,8 @@ // default. // TODO(nsatragno): add a command line flag so that it's only granted // for tests. - permission == PermissionType::BACKGROUND_SYNC; + permission == PermissionType::BACKGROUND_SYNC || + permission == PermissionType::ACCESSIBILITY_EVENTS; } } // namespace
diff --git a/content/shell/test_runner/test_runner.cc b/content/shell/test_runner/test_runner.cc index 3b66518..85fa1458 100644 --- a/content/shell/test_runner/test_runner.cc +++ b/content/shell/test_runner/test_runner.cc
@@ -99,7 +99,7 @@ static void Install(base::WeakPtr<TestRunner> test_runner, base::WeakPtr<TestRunnerForSpecificView> view_test_runner, WebLocalFrame* frame, - bool is_web_platform_tests_mode); + bool is_wpt_reftest); private: explicit TestRunnerBindings( @@ -292,7 +292,7 @@ base::WeakPtr<TestRunner> test_runner, base::WeakPtr<TestRunnerForSpecificView> view_test_runner, WebLocalFrame* frame, - bool is_web_platform_tests_mode) { + bool is_wpt_reftest) { v8::Isolate* isolate = blink::MainThreadIsolate(); v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = frame->MainWorldScriptContext(); @@ -312,33 +312,44 @@ global->Set(gin::StringToV8(isolate, "testRunner"), v8_bindings); - // The web-platform-tests suite require that reference comparison is delayed - // for any test with a 'reftest-wait' class on the root element, until that - // class attribute is removed. To support this approach, we inject some - // JavaScript that implements the same behavior using TestRunner. + // Inject some JavaScript to the top-level frame of a reftest in the + // web-platform-tests suite to have the same reftest screenshot timing as + // upstream WPT: // - // See http://web-platform-tests.org/writing-tests/reftests.html for more - // details about reference tests in the web-platform-tests suite. - if (is_web_platform_tests_mode) { + // 1. For normal reftest, we would like to take screenshots after web fonts + // are loaded, i.e. replicate the behavior of this injected script: + // https://github.com/w3c/web-platform-tests/blob/master/tools/wptrunner/wptrunner/executors/reftest-wait_webdriver.js + // 2. For reftests with a 'reftest-wait' class on the root element, reference + // comparison is delayed until that class attribute is removed. To support + // this feature, we use a mutation observer. + // http://web-platform-tests.org/writing-tests/reftests.html#controlling-when-comparison-occurs + // + // Note that this method may be called multiple times on a frame, so we put + // the code behind a flag. The flag is safe to be installed on testRunner + // because WPT reftests never access this object. + if (is_wpt_reftest && !frame->Parent()) { frame->ExecuteScript(blink::WebString( - R"(window.addEventListener('load', function() { - if (!window.testRunner) { - return; - } - const target = document.documentElement; - if (target != null && target.classList.contains('reftest-wait')) { + R"(if (!window.testRunner._wpt_reftest_setup) { + window.testRunner._wpt_reftest_setup = true; + + window.addEventListener('load', function() { window.testRunner.waitUntilDone(); - const observer = new MutationObserver(function(mutations) { - mutations.forEach(function(mutation) { - if (!target.classList.contains('reftest-wait')) { - window.testRunner.notifyDone(); - } + const target = document.documentElement; + if (target != null && target.classList.contains('reftest-wait')) { + const observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (!target.classList.contains('reftest-wait')) { + window.testRunner.notifyDone(); + } + }); }); - }); - const config = {attributes: true}; - observer.observe(target, config); - } - });)")); + const config = {attributes: true}; + observer.observe(target, config); + } else { + document.fonts.ready.then(() => window.testRunner.notifyDone()); + } + }); + })")); } } @@ -1583,8 +1594,11 @@ void TestRunner::Install( WebLocalFrame* frame, base::WeakPtr<TestRunnerForSpecificView> view_test_runner) { + // In WPT, only reftests generate pixel results. + bool is_wpt_reftest = + is_web_platform_tests_mode() && ShouldGeneratePixelResults(); TestRunnerBindings::Install(weak_factory_.GetWeakPtr(), view_test_runner, - frame, is_web_platform_tests_mode()); + frame, is_wpt_reftest); mock_screen_orientation_client_->OverrideAssociatedInterfaceProviderForFrame( frame); }
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 61e1a95..f478948 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -219,8 +219,6 @@ "mock_render_widget_host_delegate.h", "mock_ssl_host_state_delegate.cc", "mock_ssl_host_state_delegate.h", - "mock_webassociatedurlloader.cc", - "mock_webassociatedurlloader.h", "mock_webblob_registry_impl.cc", "mock_webblob_registry_impl.h", "mock_webclipboard_impl.cc", @@ -301,7 +299,7 @@ "//cc/blink", "//cc/ipc", "//components/download/public/common:public", - "//components/leveldb/public/interfaces", + "//components/services/leveldb/public/interfaces", "//components/viz/host", "//components/viz/service", "//content/app:both_for_content_tests", @@ -693,6 +691,7 @@ "../browser/accessibility/accessibility_action_browsertest.cc", "../browser/accessibility/accessibility_ipc_error_browsertest.cc", "../browser/accessibility/accessibility_mode_browsertest.cc", + "../browser/accessibility/aom_browsertest.cc", "../browser/accessibility/cross_platform_accessibility_browsertest.cc", "../browser/accessibility/dump_accessibility_browsertest_base.cc", "../browser/accessibility/dump_accessibility_browsertest_base.h", @@ -1659,12 +1658,12 @@ "//cc", "//cc:test_support", "//cc/ipc", - "//components/leveldb/public/cpp", "//components/network_session_configurator/browser", "//components/network_session_configurator/common", "//components/offline_pages/buildflags", "//components/payments/mojom", "//components/rappor:test_support", + "//components/services/leveldb/public/cpp", "//components/ukm:test_support", "//components/viz/client", "//components/viz/common", @@ -1760,7 +1759,7 @@ ] data_deps = [ - "//components/filesystem:filesystem", + "//components/services/filesystem:filesystem", "//testing/buildbot/filters:content_unittests_filters", "//third_party/mesa:osmesa", ]
diff --git a/content/test/DEPS b/content/test/DEPS index 8b65cb3..87aa8cbf 100644 --- a/content/test/DEPS +++ b/content/test/DEPS
@@ -1,7 +1,7 @@ include_rules = [ # Allow inclusion of specific components that we depend on. # See comment in content/DEPS for which components are allowed. - "+components/leveldb", + "+components/services/leveldb", "+components/network_session_configurator/common", "+components/scheduler/renderer", "+components/scheduler/test",
diff --git a/content/test/data/accessibility/aom/event-listener-on-virtual-node.html b/content/test/data/accessibility/aom/event-listener-on-virtual-node.html new file mode 100644 index 0000000..5920a13 --- /dev/null +++ b/content/test/data/accessibility/aom/event-listener-on-virtual-node.html
@@ -0,0 +1,12 @@ +<body> +<button aria-label='FocusMe'></button> +<script> + var virtualNode = new AccessibleNode(); + virtualNode.role = 'link'; + virtualNode.label = 'ClickMe'; + virtualNode.onaccessibleclick = function() { + document.querySelector('button').focus(); + }; + document.body.accessibleNode.appendChild(virtualNode); +</script> +</body>
diff --git a/content/test/fake_leveldb_database.h b/content/test/fake_leveldb_database.h index 913b2b1..8c77d6a 100644 --- a/content/test/fake_leveldb_database.h +++ b/content/test/fake_leveldb_database.h
@@ -6,7 +6,7 @@ #define CONTENT_TEST_FAKE_LEVELDB_DATABASE_H_ #include "base/memory/ref_counted.h" -#include "components/leveldb/public/interfaces/leveldb.mojom.h" +#include "components/services/leveldb/public/interfaces/leveldb.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" namespace content {
diff --git a/content/test/mock_webassociatedurlloader.cc b/content/test/mock_webassociatedurlloader.cc deleted file mode 100644 index e458fb4..0000000 --- a/content/test/mock_webassociatedurlloader.cc +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/test/mock_webassociatedurlloader.h" - -#include "third_party/WebKit/public/platform/WebData.h" -#include "third_party/WebKit/public/platform/WebURLError.h" -#include "third_party/WebKit/public/platform/WebURLRequest.h" -#include "third_party/WebKit/public/platform/WebURLResponse.h" - -namespace content { - -MockWebAssociatedURLLoader::MockWebAssociatedURLLoader() {} - -MockWebAssociatedURLLoader::~MockWebAssociatedURLLoader() {} - -} // namespace content
diff --git a/content/test/mock_webassociatedurlloader.h b/content/test/mock_webassociatedurlloader.h deleted file mode 100644 index 413ce32..0000000 --- a/content/test/mock_webassociatedurlloader.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_TEST_MOCK_WEBASSOCIATEDURLLOADER_H_ -#define CONTENT_TEST_MOCK_WEBASSOCIATEDURLLOADER_H_ - -#include "base/macros.h" -#include "base/single_thread_task_runner.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "third_party/WebKit/public/web/WebAssociatedURLLoader.h" - -namespace content { - -class MockWebAssociatedURLLoader : public blink::WebAssociatedURLLoader { - public: - MockWebAssociatedURLLoader(); - virtual ~MockWebAssociatedURLLoader(); - - MOCK_METHOD2(LoadAsynchronously, - void(const blink::WebURLRequest& request, - blink::WebAssociatedURLLoaderClient* client)); - MOCK_METHOD0(Cancel, void()); - MOCK_METHOD1(SetDefersLoading, void(bool value)); - MOCK_METHOD1(SetLoadingTaskRunner, - void(base::SingleThreadTaskRunner* loading_task_runner)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockWebAssociatedURLLoader); -}; - -} // namespace content - -#endif // CONTENT_TEST_MOCK_WEBASSOCIATEDURLLOADER_H_
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn index 8f5bf66..027023a 100644 --- a/device/fido/BUILD.gn +++ b/device/fido/BUILD.gn
@@ -88,6 +88,8 @@ "u2f_sign.cc", "u2f_sign.h", "u2f_transport_protocol.h", + "virtual_u2f_device.cc", + "virtual_u2f_device.h", ] defines = [ "IS_DEVICE_FIDO_IMPL" ] @@ -215,8 +217,6 @@ source_set("test_support") { testonly = true sources = [ - "fake_u2f_device.cc", - "fake_u2f_device.h", "fake_u2f_discovery.cc", "fake_u2f_discovery.h", "test_callback_receiver.h",
diff --git a/device/fido/u2f_apdu_command.h b/device/fido/u2f_apdu_command.h index 76973dca..d9ade7b 100644 --- a/device/fido/u2f_apdu_command.h +++ b/device/fido/u2f_apdu_command.h
@@ -14,9 +14,7 @@ namespace device { -namespace test { -class FakeU2fDevice; -} +class VirtualU2fDevice; // APDU commands are defined as part of ISO 7816-4. Commands can be serialized // into either short length encodings, where the maximum data length is 256 @@ -78,7 +76,7 @@ FRIEND_TEST_ALL_PREFIXES(U2fApduTest, TestCreateLegacyVersion); // Built-in software key for testing. - friend class test::FakeU2fDevice; + friend class VirtualU2fDevice; static constexpr size_t kApduMinHeader = 4; static constexpr size_t kApduMaxHeader = 7;
diff --git a/device/fido/u2f_register_unittest.cc b/device/fido/u2f_register_unittest.cc index 5355779..0ce22e8 100644 --- a/device/fido/u2f_register_unittest.cc +++ b/device/fido/u2f_register_unittest.cc
@@ -14,7 +14,6 @@ #include "device/fido/attested_credential_data.h" #include "device/fido/authenticator_data.h" #include "device/fido/ec_public_key.h" -#include "device/fido/fake_u2f_device.h" #include "device/fido/fake_u2f_discovery.h" #include "device/fido/fido_attestation_statement.h" #include "device/fido/mock_u2f_device.h" @@ -22,6 +21,7 @@ #include "device/fido/test_callback_receiver.h" #include "device/fido/u2f_parsing_utils.h" #include "device/fido/u2f_response_test_data.h" +#include "device/fido/virtual_u2f_device.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -403,7 +403,7 @@ request->Start(); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<test::FakeU2fDevice>(); + auto device = std::make_unique<VirtualU2fDevice>(); discovery()->AddDevice(std::move(device)); register_callback_receiver().WaitForCallback();
diff --git a/device/fido/u2f_sign_unittest.cc b/device/fido/u2f_sign_unittest.cc index 7c32ade..6317785 100644 --- a/device/fido/u2f_sign_unittest.cc +++ b/device/fido/u2f_sign_unittest.cc
@@ -11,12 +11,12 @@ #include "crypto/ec_private_key.h" #include "crypto/sha2.h" #include "device/fido/authenticator_data.h" -#include "device/fido/fake_u2f_device.h" #include "device/fido/fake_u2f_discovery.h" #include "device/fido/mock_u2f_device.h" #include "device/fido/sign_response_data.h" #include "device/fido/test_callback_receiver.h" #include "device/fido/u2f_response_test_data.h" +#include "device/fido/virtual_u2f_device.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -253,7 +253,7 @@ request->Start(); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<test::FakeU2fDevice>(); + auto device = std::make_unique<VirtualU2fDevice>(); device->AddRegistration(key_handle, std::move(private_key), GetTestRelyingPartyIdSHA256(), 42); discovery()->AddDevice(std::move(device));
diff --git a/device/fido/fake_u2f_device.cc b/device/fido/virtual_u2f_device.cc similarity index 89% rename from device/fido/fake_u2f_device.cc rename to device/fido/virtual_u2f_device.cc index 67ece10..c3c84be4 100644 --- a/device/fido/fake_u2f_device.cc +++ b/device/fido/virtual_u2f_device.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "device/fido/fake_u2f_device.h" +#include "device/fido/virtual_u2f_device.h" #include <utility> @@ -12,7 +12,6 @@ #include "device/fido/u2f_apdu_command.h" namespace device { -namespace test { namespace { @@ -81,9 +80,9 @@ } // namespace -FakeU2fDevice::RegistrationData::RegistrationData() = default; +VirtualU2fDevice::RegistrationData::RegistrationData() = default; -FakeU2fDevice::RegistrationData::RegistrationData( +VirtualU2fDevice::RegistrationData::RegistrationData( std::unique_ptr<crypto::ECPrivateKey> private_key, std::vector<uint8_t> app_id_hash, uint32_t counter) @@ -91,13 +90,13 @@ app_id_hash(std::move(app_id_hash)), counter(counter) {} -FakeU2fDevice::RegistrationData::RegistrationData(RegistrationData&& data) = +VirtualU2fDevice::RegistrationData::RegistrationData(RegistrationData&& data) = default; -FakeU2fDevice::RegistrationData& FakeU2fDevice::RegistrationData::operator=( - RegistrationData&& other) = default; -FakeU2fDevice::RegistrationData::~RegistrationData() = default; +VirtualU2fDevice::RegistrationData& VirtualU2fDevice::RegistrationData:: +operator=(RegistrationData&& other) = default; +VirtualU2fDevice::RegistrationData::~RegistrationData() = default; -FakeU2fDevice::FakeU2fDevice() +VirtualU2fDevice::VirtualU2fDevice() : attestation_private_key_( crypto::ECPrivateKey::CreateFromPrivateKeyInfo(GetAttestationKey())), attestation_cert_(std::begin(kAttestationCert), @@ -106,18 +105,18 @@ DCHECK(attestation_private_key_); } -FakeU2fDevice::~FakeU2fDevice() = default; +VirtualU2fDevice::~VirtualU2fDevice() = default; -void FakeU2fDevice::TryWink(WinkCallback cb) { +void VirtualU2fDevice::TryWink(WinkCallback cb) { std::move(cb).Run(); } -std::string FakeU2fDevice::GetId() const { +std::string VirtualU2fDevice::GetId() const { // Use our heap address to get a unique-ish number. (0xffe1 is a prime). - return "FakeU2fDevice-" + std::to_string((size_t)this % 0xffe1); + return "VirtualU2fDevice-" + std::to_string((size_t)this % 0xffe1); } -void FakeU2fDevice::AddRegistration( +void VirtualU2fDevice::AddRegistration( std::vector<uint8_t> key_handle, std::unique_ptr<crypto::ECPrivateKey> private_key, std::vector<uint8_t> app_id_hash, @@ -126,8 +125,8 @@ RegistrationData(std::move(private_key), std::move(app_id_hash), counter); } -void FakeU2fDevice::DeviceTransact(std::vector<uint8_t> command, - DeviceCallback cb) { +void VirtualU2fDevice::DeviceTransact(std::vector<uint8_t> command, + DeviceCallback cb) { // Note, here we are using the code-under-test in this fake. auto parsed_command = U2fApduCommand::CreateFromMessage(command); switch (parsed_command->ins_) { @@ -149,15 +148,15 @@ } } -base::WeakPtr<U2fDevice> FakeU2fDevice::GetWeakPtr() { +base::WeakPtr<U2fDevice> VirtualU2fDevice::GetWeakPtr() { return weak_factory_.GetWeakPtr(); } -void FakeU2fDevice::DoRegister(uint8_t ins, - uint8_t p1, - uint8_t p2, - base::span<const uint8_t> data, - DeviceCallback cb) { +void VirtualU2fDevice::DoRegister(uint8_t ins, + uint8_t p1, + uint8_t p2, + base::span<const uint8_t> data, + DeviceCallback cb) { if (data.size() != 64) { std::move(cb).Run(true, std::make_unique<U2fApduResponse>( std::vector<uint8_t>(), @@ -226,11 +225,11 @@ std::move(response), U2fApduResponse::Status::SW_NO_ERROR)); } -void FakeU2fDevice::DoSign(uint8_t ins, - uint8_t p1, - uint8_t p2, - base::span<const uint8_t> data, - DeviceCallback cb) { +void VirtualU2fDevice::DoSign(uint8_t ins, + uint8_t p1, + uint8_t p2, + base::span<const uint8_t> data, + DeviceCallback cb) { if (!(p1 == U2fApduCommand::kP1CheckOnly || p1 == U2fApduCommand::kP1TupRequiredConsumed || p1 == U2fApduCommand::kP1IndividualAttestation) || @@ -315,5 +314,4 @@ std::move(response), U2fApduResponse::Status::SW_NO_ERROR)); } -} // namespace test } // namespace device
diff --git a/device/fido/fake_u2f_device.h b/device/fido/virtual_u2f_device.h similarity index 86% rename from device/fido/fake_u2f_device.h rename to device/fido/virtual_u2f_device.h index 6c86d47ec..b6e3a774 100644 --- a/device/fido/fake_u2f_device.h +++ b/device/fido/virtual_u2f_device.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef DEVICE_FIDO_FAKE_U2F_DEVICE_H_ -#define DEVICE_FIDO_FAKE_U2F_DEVICE_H_ +#ifndef DEVICE_FIDO_VIRTUAL_U2F_DEVICE_H_ +#define DEVICE_FIDO_VIRTUAL_U2F_DEVICE_H_ #include <stdint.h> @@ -12,6 +12,7 @@ #include <string> #include <vector> +#include "base/component_export.h" #include "base/containers/span.h" #include "base/macros.h" #include "device/fido/u2f_device.h" @@ -21,12 +22,11 @@ } // namespace crypto namespace device { -namespace test { -class FakeU2fDevice : public U2fDevice { +class COMPONENT_EXPORT(DEVICE_FIDO) VirtualU2fDevice : public U2fDevice { public: - FakeU2fDevice(); - ~FakeU2fDevice() override; + VirtualU2fDevice(); + ~VirtualU2fDevice() override; void AddRegistration(std::vector<uint8_t> key_handle, std::unique_ptr<crypto::ECPrivateKey> private_key, @@ -77,10 +77,9 @@ std::map<std::vector<uint8_t>, RegistrationData> registrations_; base::WeakPtrFactory<U2fDevice> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(FakeU2fDevice); + DISALLOW_COPY_AND_ASSIGN(VirtualU2fDevice); }; -} // namespace test } // namespace device -#endif // DEVICE_FIDO_FAKE_U2F_DEVICE_H_ +#endif // DEVICE_FIDO_VIRTUAL_U2F_DEVICE_H_
diff --git a/extensions/browser/content_verifier.cc b/extensions/browser/content_verifier.cc index 790137f..41defa93 100644 --- a/extensions/browser/content_verifier.cc +++ b/extensions/browser/content_verifier.cc
@@ -206,6 +206,12 @@ fetcher_->ExtensionUnloaded(extension); } +GURL ContentVerifier::GetSignatureFetchUrlForTest( + const ExtensionId& extension_id, + const base::Version& extension_version) { + return delegate_->GetSignatureFetchUrl(extension_id, extension_version); +} + void ContentVerifier::OnFetchCompleteHelper( const std::string& extension_id, bool should_verify_any_paths_result) {
diff --git a/extensions/browser/content_verifier.h b/extensions/browser/content_verifier.h index 1a41c80..d89c5a9e 100644 --- a/extensions/browser/content_verifier.h +++ b/extensions/browser/content_verifier.h
@@ -74,6 +74,9 @@ const Extension* extension, UnloadedExtensionReason reason) override; + GURL GetSignatureFetchUrlForTest(const ExtensionId& extension_id, + const base::Version& extension_version); + private: DISALLOW_COPY_AND_ASSIGN(ContentVerifier);
diff --git a/extensions/browser/content_verifier/test_utils.cc b/extensions/browser/content_verifier/test_utils.cc index 906d1a1..30a5faf 100644 --- a/extensions/browser/content_verifier/test_utils.cc +++ b/extensions/browser/content_verifier/test_utils.cc
@@ -13,18 +13,19 @@ namespace extensions { -TestContentVerifyJobObserver::TestContentVerifyJobObserver( +// TestContentVerifySingleJobObserver ------------------------------------------ +TestContentVerifySingleJobObserver::TestContentVerifySingleJobObserver( const ExtensionId& extension_id, const base::FilePath& relative_path) : extension_id_(extension_id), relative_path_(relative_path) { ContentVerifyJob::SetObserverForTests(this); } -TestContentVerifyJobObserver::~TestContentVerifyJobObserver() { +TestContentVerifySingleJobObserver::~TestContentVerifySingleJobObserver() { ContentVerifyJob::SetObserverForTests(nullptr); } -void TestContentVerifyJobObserver::JobFinished( +void TestContentVerifySingleJobObserver::JobFinished( const ExtensionId& extension_id, const base::FilePath& relative_path, ContentVerifyJob::FailureReason reason) { @@ -35,7 +36,7 @@ job_finished_run_loop_.Quit(); } -void TestContentVerifyJobObserver::OnHashesReady( +void TestContentVerifySingleJobObserver::OnHashesReady( const ExtensionId& extension_id, const base::FilePath& relative_path, bool success) { @@ -47,18 +48,86 @@ } ContentVerifyJob::FailureReason -TestContentVerifyJobObserver::WaitForJobFinished() { +TestContentVerifySingleJobObserver::WaitForJobFinished() { // Run() returns immediately if Quit() has already been called. job_finished_run_loop_.Run(); EXPECT_TRUE(failure_reason_.has_value()); return failure_reason_.value_or(ContentVerifyJob::FAILURE_REASON_MAX); } -void TestContentVerifyJobObserver::WaitForOnHashesReady() { +void TestContentVerifySingleJobObserver::WaitForOnHashesReady() { // Run() returns immediately if Quit() has already been called. on_hashes_ready_run_loop_.Run(); } +// TestContentVerifyJobObserver ------------------------------------------------ +void TestContentVerifyJobObserver::ExpectJobResult( + const ExtensionId& extension_id, + const base::FilePath& relative_path, + Result expected_result) { + expectations_.push_back( + ExpectedResult(extension_id, relative_path, expected_result)); +} + +TestContentVerifyJobObserver::TestContentVerifyJobObserver() { + EXPECT_TRUE( + content::BrowserThread::GetCurrentThreadIdentifier(&creation_thread_)); + ContentVerifyJob::SetObserverForTests(this); +} + +TestContentVerifyJobObserver::~TestContentVerifyJobObserver() { + ContentVerifyJob::SetObserverForTests(nullptr); +} + +bool TestContentVerifyJobObserver::WaitForExpectedJobs() { + EXPECT_TRUE(content::BrowserThread::CurrentlyOn(creation_thread_)); + if (!expectations_.empty()) { + base::RunLoop run_loop; + job_quit_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + } + return expectations_.empty(); +} + +void TestContentVerifyJobObserver::JobStarted( + const ExtensionId& extension_id, + const base::FilePath& relative_path) {} + +void TestContentVerifyJobObserver::JobFinished( + const ExtensionId& extension_id, + const base::FilePath& relative_path, + ContentVerifyJob::FailureReason failure_reason) { + if (!content::BrowserThread::CurrentlyOn(creation_thread_)) { + content::BrowserThread::PostTask( + creation_thread_, FROM_HERE, + base::BindOnce(&TestContentVerifyJobObserver::JobFinished, + base::Unretained(this), extension_id, relative_path, + failure_reason)); + return; + } + Result result = failure_reason == ContentVerifyJob::NONE ? Result::SUCCESS + : Result::FAILURE; + bool found = false; + for (std::list<ExpectedResult>::iterator i = expectations_.begin(); + i != expectations_.end(); ++i) { + if (i->extension_id == extension_id && i->path == relative_path && + i->result == result) { + found = true; + expectations_.erase(i); + break; + } + } + if (found) { + if (expectations_.empty() && job_quit_closure_) + std::move(job_quit_closure_).Run(); + } else { + LOG(WARNING) << "Ignoring unexpected JobFinished " << extension_id << "/" + << relative_path.value() + << " failure_reason:" << failure_reason; + } +} + +// MockContentVerifierDelegate ------------------------------------------------ MockContentVerifierDelegate::MockContentVerifierDelegate() = default; MockContentVerifierDelegate::~MockContentVerifierDelegate() = default; @@ -95,6 +164,32 @@ void MockContentVerifierDelegate::Shutdown() {} +// VerifierObserver ----------------------------------------------------------- +VerifierObserver::VerifierObserver() { + ContentVerifier::SetObserverForTests(this); +} + +VerifierObserver::~VerifierObserver() { + ContentVerifier::SetObserverForTests(nullptr); +} + +void VerifierObserver::WaitForFetchComplete(const ExtensionId& extension_id) { + EXPECT_TRUE(id_to_wait_for_.empty()); + EXPECT_EQ(loop_runner_.get(), nullptr); + id_to_wait_for_ = extension_id; + loop_runner_ = new content::MessageLoopRunner(); + loop_runner_->Run(); + id_to_wait_for_.clear(); + loop_runner_ = nullptr; +} + +void VerifierObserver::OnFetchComplete(const ExtensionId& extension_id, + bool success) { + completed_fetches_.insert(extension_id); + if (extension_id == id_to_wait_for_) + loop_runner_->Quit(); +} + namespace content_verifier_test_utils { scoped_refptr<Extension> UnzipToDirAndLoadExtension(
diff --git a/extensions/browser/content_verifier/test_utils.h b/extensions/browser/content_verifier/test_utils.h index 93c3a5bb4..1797d3a 100644 --- a/extensions/browser/content_verifier/test_utils.h +++ b/extensions/browser/content_verifier/test_utils.h
@@ -8,6 +8,9 @@ #include "base/files/file_path.h" #include "base/optional.h" #include "base/run_loop.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/test/test_utils.h" +#include "extensions/browser/content_verifier.h" #include "extensions/browser/content_verifier_delegate.h" #include "extensions/browser/content_verify_job.h" #include "extensions/common/extension_id.h" @@ -16,14 +19,14 @@ class Extension; -// Test class to observe a particular extension resource's ContentVerifyJob +// Test class to observe *a particular* extension resource's ContentVerifyJob // lifetime. Provides a way to wait for a job to finish and return // the job's result. -class TestContentVerifyJobObserver : ContentVerifyJob::TestObserver { +class TestContentVerifySingleJobObserver : ContentVerifyJob::TestObserver { public: - TestContentVerifyJobObserver(const ExtensionId& extension_id, - const base::FilePath& relative_path); - ~TestContentVerifyJobObserver(); + TestContentVerifySingleJobObserver(const ExtensionId& extension_id, + const base::FilePath& relative_path); + ~TestContentVerifySingleJobObserver(); // ContentVerifyJob::TestObserver: void JobStarted(const ExtensionId& extension_id, @@ -50,6 +53,53 @@ base::Optional<ContentVerifyJob::FailureReason> failure_reason_; bool seen_on_hashes_ready_ = false; + DISALLOW_COPY_AND_ASSIGN(TestContentVerifySingleJobObserver); +}; + +// Test class to observe expected set of ContentVerifyJobs. +class TestContentVerifyJobObserver : public ContentVerifyJob::TestObserver { + public: + TestContentVerifyJobObserver(); + virtual ~TestContentVerifyJobObserver(); + + enum class Result { SUCCESS, FAILURE }; + + // Call this to add an expected job result. + void ExpectJobResult(const ExtensionId& extension_id, + const base::FilePath& relative_path, + Result expected_result); + + // Wait to see expected jobs. Returns true when we've seen all expected jobs + // finish, or false if there was an error or timeout. + bool WaitForExpectedJobs(); + + // ContentVerifyJob::TestObserver interface + void JobStarted(const ExtensionId& extension_id, + const base::FilePath& relative_path) override; + void JobFinished(const ExtensionId& extension_id, + const base::FilePath& relative_path, + ContentVerifyJob::FailureReason failure_reason) override; + void OnHashesReady(const ExtensionId& extension_id, + const base::FilePath& relative_path, + bool success) override {} + + private: + struct ExpectedResult { + public: + ExtensionId extension_id; + base::FilePath path; + Result result; + + ExpectedResult(const ExtensionId& extension_id, + const base::FilePath& path, + Result result) + : extension_id(extension_id), path(path), result(result) {} + }; + std::list<ExpectedResult> expectations_; + content::BrowserThread::ID creation_thread_; + // Accessed on |creation_thread_|. + base::OnceClosure job_quit_closure_; + DISALLOW_COPY_AND_ASSIGN(TestContentVerifyJobObserver); }; @@ -76,6 +126,28 @@ DISALLOW_COPY_AND_ASSIGN(MockContentVerifierDelegate); }; +// Observes ContentVerifier::OnFetchComplete of a particular extension. +class VerifierObserver : public ContentVerifier::TestObserver { + public: + VerifierObserver(); + virtual ~VerifierObserver(); + + const std::set<ExtensionId>& completed_fetches() { + return completed_fetches_; + } + + // Returns when we've seen OnFetchComplete for |extension_id|. + void WaitForFetchComplete(const ExtensionId& extension_id); + + // ContentVerifier::TestObserver + void OnFetchComplete(const ExtensionId& extension_id, bool success) override; + + private: + std::set<ExtensionId> completed_fetches_; + ExtensionId id_to_wait_for_; + scoped_refptr<content::MessageLoopRunner> loop_runner_; +}; + namespace content_verifier_test_utils { // Unzips the extension source from |extension_zip| into |unzip_dir|
diff --git a/extensions/browser/content_verify_job_unittest.cc b/extensions/browser/content_verify_job_unittest.cc index cf4fa54..d43f0fc 100644 --- a/extensions/browser/content_verify_job_unittest.cc +++ b/extensions/browser/content_verify_job_unittest.cc
@@ -61,7 +61,7 @@ const base::FilePath& resource_path, std::string& resource_contents, ContentVerifyJobAsyncRunMode run_mode) { - TestContentVerifyJobObserver observer(extension.id(), resource_path); + TestContentVerifySingleJobObserver observer(extension.id(), resource_path); scoped_refptr<ContentVerifyJob> verify_job = new ContentVerifyJob( extension.id(), extension.version(), extension.path(), resource_path, ContentVerifierKey(kWebstoreSignaturesPublicKey,
diff --git a/extensions/browser/updater/extension_downloader.cc b/extensions/browser/updater/extension_downloader.cc index c2342794..d4cd9741 100644 --- a/extensions/browser/updater/extension_downloader.cc +++ b/extensions/browser/updater/extension_downloader.cc
@@ -157,10 +157,10 @@ } // namespace const char ExtensionDownloader::kUpdateInteractivityHeader[] = - "X-GoogleUpdate-Interactivity"; -const char ExtensionDownloader::kUpdateAppIdHeader[] = "X-GoogleUpdate-AppId"; + "X-Goog-Update-Interactivity"; +const char ExtensionDownloader::kUpdateAppIdHeader[] = "X-Goog-Update-AppId"; const char ExtensionDownloader::kUpdateUpdaterHeader[] = - "X-GoogleUpdate-Updater"; + "X-Goog-Update-Updater"; const char ExtensionDownloader::kUpdateInteractivityForeground[] = "fg"; const char ExtensionDownloader::kUpdateInteractivityBackground[] = "bg";
diff --git a/gin/test/run_all_unittests.cc b/gin/test/run_all_unittests.cc index 25500a6..b6a86bdd 100644 --- a/gin/test/run_all_unittests.cc +++ b/gin/test/run_all_unittests.cc
@@ -10,6 +10,6 @@ base::TestSuite test_suite(argc, argv); return base::LaunchUnitTests( - argc, argv, base::Bind(&base::TestSuite::Run, - base::Unretained(&test_suite))); + argc, argv, + base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite))); }
diff --git a/headless/lib/browser/headless_url_request_context_getter.cc b/headless/lib/browser/headless_url_request_context_getter.cc index ea2eabd4..a24ae19b 100644 --- a/headless/lib/browser/headless_url_request_context_getter.cc +++ b/headless/lib/browser/headless_url_request_context_getter.cc
@@ -147,11 +147,33 @@ builder.set_data_enabled(true); builder.set_file_enabled(true); if (proxy_config_) { - // TODO(https://crbug.com/656607): Add proper traffic annotation. + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("proxy_config_headless", R"( + semantics { + sender: "Proxy Config" + description: + "Creates a proxy based on configuration received from headless " + "command prompt." + trigger: + "User starts headless with proxy config." + data: + "Proxy configurations." + destination: OTHER + destination_other: + "The proxy server specified in the configuration." + } + policy { + cookies_allowed: NO + setting: + "This config is only used for headless mode and provided by user." + policy_exception_justification: + "This config is only used for headless mode and provided by user." + })"); + builder.set_proxy_resolution_service( net::ProxyResolutionService::CreateFixed( - net::ProxyConfigWithAnnotation( - *proxy_config_, NO_TRAFFIC_ANNOTATION_BUG_656607))); + net::ProxyConfigWithAnnotation(*proxy_config_, + traffic_annotation))); } else { builder.set_proxy_config_service(std::move(proxy_config_service_)); }
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index d45380a..0560ebb 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -618,9 +618,21 @@ <message name="IDS_IOS_DOWNLOAD_MANAGER_UNABLE_TO_OPEN_FILE" desc="Title of dialog displayed when the user attempts to open a downloaded file and no app on the device can open the file. [Length: 25em] [iOS only]"> Unable to Open File </message> + <message name="IDS_IOS_DOWNLOAD_MANAGER_FAILED_ACCESSIBILITY_ANNOUNCEMENT" desc="The accessibility announcement read by Voice Over when the download has failed. [Length: unlimited] [iOS only]"> + Download failed + </message> + <message name="IDS_IOS_DOWNLOAD_MANAGER_SUCCEEDED_ACCESSIBILITY_ANNOUNCEMENT" desc="The accessibility announcement read by Voice Over when the download has sucessfully finished. [Length: unlimited] [iOS only]"> + Download successfully finished + </message> + <message name="IDS_IOS_DOWNLOAD_MANAGER_REQUESTED_ACCESSIBILITY_ANNOUNCEMENT" desc="The accessibility announcement read by Voice Over when the Download Manager UI is shown to the user. [Length: unlimited] [iOS only]"> + File download is available + </message> <message name="IDS_IOS_DOWNLOAD_MANAGER_UPLOAD_TO_GOOGLE_DRIVE" desc="Button for uploading a downloaded file to Google Drive. It's displayed on the dialog presented when no app on the device can open the file. [Length: 25em] [iOS only]"> Upload to Google Drive </message> + <message name="IDS_IOS_DOWNLOAD_MANAGER_GOOGLE_DRIVE" desc="Button for installing Google Drive app. Google Drive is a product name and should use the correct localized version of the product name. [Length: 25em] [iOS only]"> + Google Drive + </message> <message name="IDS_IOS_FACETIME_BUTTON" desc="Text in the confirmation dialog button that will initiate a FaceTime call for the presented number. [Length: 10em] [iOS only]"> FaceTime </message>
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 0d64d617..df719f7 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -4778,15 +4778,13 @@ - (id<ToolbarSnapshotProviding>)toolbarSnapshotProvider { id<ToolbarSnapshotProviding> toolbarSnapshotProvider = nil; - if (_toolbarCoordinator.viewController.view.hidden) { - Tab* currentTab = [_model currentTab]; - if (currentTab.webState && - UrlHasChromeScheme(currentTab.webState->GetLastCommittedURL())) { - // Use the native content controller's toolbar when the BVC's is hidden. - id nativeController = [self nativeControllerForTab:currentTab]; - if ([nativeController conformsToProtocol:@protocol(ToolbarOwner)]) { - toolbarSnapshotProvider = [nativeController toolbarSnapshotProvider]; - } + Tab* currentTab = [_model currentTab]; + if (_toolbarCoordinator.viewController.view.hidden && currentTab.webState && + UrlHasChromeScheme(currentTab.webState->GetLastCommittedURL())) { + // Use the native content controller's toolbar when the BVC's is hidden. + id nativeController = [self nativeControllerForTab:currentTab]; + if ([nativeController conformsToProtocol:@protocol(ToolbarOwner)]) { + toolbarSnapshotProvider = [nativeController toolbarSnapshotProvider]; } } else { toolbarSnapshotProvider = _toolbarCoordinator;
diff --git a/ios/chrome/browser/ui/download/BUILD.gn b/ios/chrome/browser/ui/download/BUILD.gn index fa0f462..c0c8813e 100644 --- a/ios/chrome/browser/ui/download/BUILD.gn +++ b/ios/chrome/browser/ui/download/BUILD.gn
@@ -44,6 +44,8 @@ "//ios/chrome/browser/ui/presenters", "//ios/chrome/browser/ui/util", "//ios/chrome/browser/web:web_internal", + "//ios/public/provider/chrome/browser", + "//ios/public/provider/chrome/browser/images", "//ios/third_party/material_components_ios", "//ios/third_party/material_roboto_font_loader_ios", "//ios/web",
diff --git a/ios/chrome/browser/ui/download/download_manager_coordinator.mm b/ios/chrome/browser/ui/download/download_manager_coordinator.mm index 13144709..3705f5f 100644 --- a/ios/chrome/browser/ui/download/download_manager_coordinator.mm +++ b/ios/chrome/browser/ui/download/download_manager_coordinator.mm
@@ -69,7 +69,6 @@ } [_confirmationDialog dismissViewControllerAnimated:YES completion:nil]; _confirmationDialog = nil; - _mediator.SetDownloadTask(nullptr); _downloadTask = nullptr; [_storeKitCoordinator stop]; @@ -108,14 +107,9 @@ l10n_util::GetNSString(IDS_IOS_DOWNLOAD_MANAGER_REPLACE_CONFIRMATION); NSString* message = l10n_util::GetNSString( IDS_IOS_DOWNLOAD_MANAGER_REPLACE_CONFIRMATION_MESSAGE); - __weak DownloadManagerCoordinator* weakSelf = self; [self runConfirmationDialogWithTitle:title message:message completionHandler:^(BOOL confirmed) { - DownloadManagerCoordinator* strongSelf = weakSelf; - if (strongSelf) { - strongSelf->_mediator.SetDownloadTask(nullptr); - } handler(confirmed ? kNewDownloadPolicyReplace : kNewDownloadPolicyDiscard); }];
diff --git a/ios/chrome/browser/ui/download/download_manager_mediator.h b/ios/chrome/browser/ui/download/download_manager_mediator.h index f68b538..a6e618e5 100644 --- a/ios/chrome/browser/ui/download/download_manager_mediator.h +++ b/ios/chrome/browser/ui/download/download_manager_mediator.h
@@ -60,8 +60,13 @@ // Converts DownloadTask progress [0;100] to float progress [0.0f;1.0f]. float GetDownloadManagerProgress() const; + // Returns accessibility announcement for download state change. -1 if there + // is no announcement. + int GetDownloadManagerA11yAnnouncement() const; + // web::DownloadTaskObserver overrides: void OnDownloadUpdated(web::DownloadTask* task) override; + void OnDownloadDestroyed(web::DownloadTask* task) override; web::DownloadTask* task_ = nullptr; __weak id<DownloadManagerConsumer> consumer_ = nil;
diff --git a/ios/chrome/browser/ui/download/download_manager_mediator.mm b/ios/chrome/browser/ui/download/download_manager_mediator.mm index 6ab8290..48117b8 100644 --- a/ios/chrome/browser/ui/download/download_manager_mediator.mm +++ b/ios/chrome/browser/ui/download/download_manager_mediator.mm
@@ -4,6 +4,8 @@ #import "ios/chrome/browser/ui/download/download_manager_mediator.h" +#include <UIKit/UIKit.h> + #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/strings/sys_string_conversions.h" @@ -11,16 +13,20 @@ #include "base/task_scheduler/post_task.h" #include "ios/chrome/browser/download/download_directory_util.h" #import "ios/chrome/browser/download/google_drive_app_util.h" +#include "ios/chrome/grit/ios_strings.h" #import "ios/web/public/download/download_task.h" #include "net/base/net_errors.h" #include "net/url_request/url_fetcher_response_writer.h" +#include "ui/base/l10n/l10n_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif DownloadManagerMediator::DownloadManagerMediator() : weak_ptr_factory_(this) {} -DownloadManagerMediator::~DownloadManagerMediator() {} +DownloadManagerMediator::~DownloadManagerMediator() { + SetDownloadTask(nullptr); +} void DownloadManagerMediator::SetConsumer( id<DownloadManagerConsumer> consumer) { @@ -90,6 +96,10 @@ UpdateConsumer(); } +void DownloadManagerMediator::OnDownloadDestroyed(web::DownloadTask* task) { + SetDownloadTask(nullptr); +} + void DownloadManagerMediator::UpdateConsumer() { DownloadManagerState state = GetDownloadManagerState(); if (state == kDownloadManagerStateSucceeded && !IsGoogleDriveAppInstalled()) { @@ -102,6 +112,12 @@ [consumer_ setProgress:GetDownloadManagerProgress()]; [consumer_ setFileName:base::SysUTF16ToNSString(task_->GetSuggestedFilename())]; + + int a11y_announcement = GetDownloadManagerA11yAnnouncement(); + if (a11y_announcement != -1) { + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, + l10n_util::GetNSString(a11y_announcement)); + } } DownloadManagerState DownloadManagerMediator::GetDownloadManagerState() const { @@ -119,6 +135,20 @@ } } +int DownloadManagerMediator::GetDownloadManagerA11yAnnouncement() const { + switch (task_->GetState()) { + case web::DownloadTask::State::kNotStarted: + return IDS_IOS_DOWNLOAD_MANAGER_REQUESTED_ACCESSIBILITY_ANNOUNCEMENT; + case web::DownloadTask::State::kComplete: + return task_->GetErrorCode() + ? IDS_IOS_DOWNLOAD_MANAGER_FAILED_ACCESSIBILITY_ANNOUNCEMENT + : IDS_IOS_DOWNLOAD_MANAGER_SUCCEEDED_ACCESSIBILITY_ANNOUNCEMENT; + case web::DownloadTask::State::kCancelled: + case web::DownloadTask::State::kInProgress: + return -1; + } +} + float DownloadManagerMediator::GetDownloadManagerProgress() const { if (task_->GetPercentComplete() == -1) return 0.0f;
diff --git a/ios/chrome/browser/ui/download/download_manager_mediator_unittest.mm b/ios/chrome/browser/ui/download/download_manager_mediator_unittest.mm index 51441ed..fd62498c 100644 --- a/ios/chrome/browser/ui/download/download_manager_mediator_unittest.mm +++ b/ios/chrome/browser/ui/download/download_manager_mediator_unittest.mm
@@ -82,8 +82,6 @@ base::FilePath download_dir; ASSERT_TRUE(GetDownloadsDirectory(&download_dir)); EXPECT_TRUE(download_dir.IsParent(file)); - - mediator_.SetDownloadTask(nullptr); } // Tests starting and failing the download. Simulates download failure from @@ -100,8 +98,6 @@ return consumer_.state == kDownloadManagerStateFailed; })); EXPECT_FALSE(consumer_.installDriveButtonVisible); - - mediator_.SetDownloadTask(nullptr); } // Tests that consumer is updated right after it's set. @@ -124,8 +120,6 @@ EXPECT_EQ(kTestTotalBytes, consumer_.countOfBytesExpectedToReceive); EXPECT_EQ(kTestReceivedBytes, consumer_.countOfBytesReceived); EXPECT_FLOAT_EQ(0.8f, consumer_.progress); - - mediator_.SetDownloadTask(nullptr); } // Tests that consumer changes the state to kDownloadManagerStateFailed if task @@ -138,8 +132,6 @@ task()->SetDone(true); EXPECT_EQ(kDownloadManagerStateFailed, consumer_.state); EXPECT_FALSE(consumer_.installDriveButtonVisible); - - mediator_.SetDownloadTask(nullptr); } // Tests that consumer changes the state to kDownloadManagerStateSucceeded if @@ -153,8 +145,6 @@ task()->SetDone(true); EXPECT_EQ(kDownloadManagerStateSucceeded, consumer_.state); EXPECT_FALSE(consumer_.installDriveButtonVisible); - - mediator_.SetDownloadTask(nullptr); } // Tests that consumer changes the state to kDownloadManagerStateSucceeded if @@ -169,8 +159,6 @@ task()->SetDone(true); EXPECT_EQ(kDownloadManagerStateSucceeded, consumer_.state); EXPECT_TRUE(consumer_.installDriveButtonVisible); - - mediator_.SetDownloadTask(nullptr); } // Tests that consumer changes the state to kDownloadManagerStateInProgress if @@ -183,6 +171,4 @@ EXPECT_EQ(kDownloadManagerStateInProgress, consumer_.state); EXPECT_FALSE(consumer_.installDriveButtonVisible); EXPECT_EQ(0.0, consumer_.progress); - - mediator_.SetDownloadTask(nullptr); }
diff --git a/ios/chrome/browser/ui/download/download_manager_view_controller.h b/ios/chrome/browser/ui/download/download_manager_view_controller.h index b9db9cc..e5a23a8 100644 --- a/ios/chrome/browser/ui/download/download_manager_view_controller.h +++ b/ios/chrome/browser/ui/download/download_manager_view_controller.h
@@ -68,6 +68,14 @@ // setInstallGoogleDriveButtonVisible:animated: was called with YES. @property(nonatomic, readonly) UIButton* installDriveButton; +// Install Google Drive app icon. Only visible if +// setInstallGoogleDriveButtonVisible:animated: was called with YES. +@property(nonatomic, readonly) UIImageView* installDriveIcon; + +// Install Google Drive label. Only visible if +// setInstallGoogleDriveButtonVisible:animated: was called with YES. +@property(nonatomic, readonly) UILabel* installDriveLabel; + // View that represents download progress. @property(nonatomic, readonly) RadialProgressView* progressView;
diff --git a/ios/chrome/browser/ui/download/download_manager_view_controller.mm b/ios/chrome/browser/ui/download/download_manager_view_controller.mm index f8c57230..51a7d1e2 100644 --- a/ios/chrome/browser/ui/download/download_manager_view_controller.mm +++ b/ios/chrome/browser/ui/download/download_manager_view_controller.mm
@@ -10,6 +10,8 @@ #import "ios/chrome/browser/ui/download/radial_progress_view.h" #import "ios/chrome/browser/ui/util/named_guide.h" #include "ios/chrome/grit/ios_strings.h" +#include "ios/public/provider/chrome/browser/chrome_browser_provider.h" +#import "ios/public/provider/chrome/browser/images/branded_image_provider.h" #import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" #import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #include "ui/base/l10n/l10n_util_mac.h" @@ -45,6 +47,8 @@ UILabel* _statusLabel; UIButton* _actionButton; UIButton* _installDriveButton; + UIImageView* _installDriveIcon; + UILabel* _installDriveLabel; RadialProgressView* _progressView; NSString* _fileName; @@ -107,6 +111,8 @@ [self.downloadControlsRow addSubview:self.progressView]; [self.downloadControlsRow addSubview:self.actionButton]; [self.installDriveControlsRow addSubview:self.installDriveButton]; + [self.installDriveControlsRow addSubview:self.installDriveIcon]; + [self.installDriveControlsRow addSubview:self.installDriveLabel]; [self.installDriveControlsRow addSubview:self.horizontalLine]; NamedGuide* actionButtonGuide = @@ -225,6 +231,29 @@ constant:-kElementMargin], ]]; + // install google drive icon constraints. + UIImageView* installDriveIcon = self.installDriveIcon; + [NSLayoutConstraint activateConstraints:@[ + [installDriveIcon.centerYAnchor + constraintEqualToAnchor:installDriveRow.centerYAnchor], + [installDriveIcon.leadingAnchor + constraintEqualToAnchor:installDriveRow.layoutMarginsGuide + .leadingAnchor], + ]]; + + // install google drive label constraints. + UILabel* installDriveLabel = self.installDriveLabel; + [NSLayoutConstraint activateConstraints:@[ + [installDriveLabel.centerYAnchor + constraintEqualToAnchor:installDriveRow.centerYAnchor], + [installDriveLabel.leadingAnchor + constraintEqualToAnchor:installDriveIcon.trailingAnchor + constant:kElementMargin], + [installDriveLabel.trailingAnchor + constraintLessThanOrEqualToAnchor:installDriveButton.leadingAnchor + constant:-kElementMargin], + ]]; + // constraint line which separates download controls and install drive rows. UIView* horizontalLine = self.horizontalLine; [NSLayoutConstraint activateConstraints:@[ @@ -401,6 +430,29 @@ return _installDriveButton; } +- (UIImageView*)installDriveIcon { + if (!_installDriveIcon) { + _installDriveIcon = [[UIImageView alloc] initWithFrame:CGRectZero]; + _installDriveIcon.translatesAutoresizingMaskIntoConstraints = NO; + _installDriveIcon.image = ios::GetChromeBrowserProvider() + ->GetBrandedImageProvider() + ->GetDownloadGoogleDriveImage(); + } + return _installDriveIcon; +} + +- (UILabel*)installDriveLabel { + if (!_installDriveLabel) { + _installDriveLabel = [[UILabel alloc] initWithFrame:CGRectZero]; + _installDriveLabel.translatesAutoresizingMaskIntoConstraints = NO; + _installDriveLabel.font = [MDCTypography subheadFont]; + _installDriveLabel.text = + l10n_util::GetNSString(IDS_IOS_DOWNLOAD_MANAGER_GOOGLE_DRIVE); + [_installDriveLabel sizeToFit]; + } + return _installDriveLabel; +} + - (RadialProgressView*)progressView { if (!_progressView) { _progressView = [[RadialProgressView alloc] initWithFrame:CGRectZero];
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_consumer.h b/ios/chrome/browser/ui/location_bar/location_bar_consumer.h index 3b6c10f9..446e4d1 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_consumer.h +++ b/ios/chrome/browser/ui/location_bar/location_bar_consumer.h
@@ -12,6 +12,9 @@ // text and the cursor position. - (void)updateOmniboxState; +// Notifies consumer to defocus the omnibox (for example on tab change). +- (void)defocusOmnibox; + @end #endif // IOS_CHROME_BROWSER_UI_LOCATION_BAR_LOCATION_BAR_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm index a228f0d..3384e3d 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
@@ -142,16 +142,6 @@ return self.omniboxPopupCoordinator.hasResults; } -#pragma mark - LocationBarConsumer - -- (void)updateOmniboxState { - if (!_locationBarController) - return; - _locationBarController->SetShouldShowHintText( - [self.delegate shouldDisplayHintText]); - _locationBarController->OnToolbarUpdated(); -} - - (BOOL)showingOmniboxPopup { OmniboxViewIOS* omniboxViewIOS = static_cast<OmniboxViewIOS*>( _locationBarController.get()->GetLocationEntry()); @@ -178,6 +168,20 @@ [self.locationBarView addContractOmniboxAnimations:animator]; } +#pragma mark - LocationBarConsumer + +- (void)updateOmniboxState { + if (!_locationBarController) + return; + _locationBarController->SetShouldShowHintText( + [self.delegate shouldDisplayHintText]); + _locationBarController->OnToolbarUpdated(); +} + +- (void)defocusOmnibox { + [self cancelOmniboxEdit]; +} + #pragma mark - VoiceSearchControllerDelegate - (void)receiveVoiceSearchResult:(NSString*)result {
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm b/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm index 35f6b12..75211757 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm
@@ -115,6 +115,7 @@ reason:(int)reason { DCHECK_EQ(_webStateList, webStateList); self.webState = newWebState; + [self.consumer defocusOmnibox]; } #pragma mark - Setters
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_mediator_unittest.mm b/ios/chrome/browser/ui/location_bar/location_bar_mediator_unittest.mm index 2fd0fe8..df4e714 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_mediator_unittest.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_mediator_unittest.mm
@@ -213,3 +213,15 @@ EXPECT_OCMOCK_VERIFY(consumer_); } + +// Test the omnibox is defocused when the active webstate is changed. +TEST_F(LocationBarMediatorTest, TestChangeActiveWebState) { + mediator_.webStateList = web_state_list_.get(); + SetUpActiveWebState(); + mediator_.consumer = consumer_; + + OCMExpect([consumer_ defocusOmnibox]); + web_state_list_->ActivateWebStateAt(1); + + EXPECT_OCMOCK_VERIFY(consumer_); +}
diff --git a/ios/chrome/browser/ui/settings/sync_utils/sync_fake_server_egtest.mm b/ios/chrome/browser/ui/settings/sync_utils/sync_fake_server_egtest.mm index 26e907d..54c011ad 100644 --- a/ios/chrome/browser/ui/settings/sync_utils/sync_fake_server_egtest.mm +++ b/ios/chrome/browser/ui/settings/sync_utils/sync_fake_server_egtest.mm
@@ -132,14 +132,7 @@ // Tests that a bookmark added on the client (before Sync is enabled) is // uploaded to the Sync server once Sync is turned on. // TODO(crbug.com/814990): Reenable the test. -#if TARGET_IPHONE_SIMULATOR -#define MAYBE_testSyncUploadBookmarkOnFirstSync \ - FLAKY_testSyncUploadBookmarkOnFirstSync -#else -#define MAYBE_testSyncUploadBookmarkOnFirstSync \ - testSyncUploadBookmarkOnFirstSync -#endif -- (void)MAYBE_testSyncUploadBookmarkOnFirstSync { +- (void)FLAKY_testSyncUploadBookmarkOnFirstSync { [self addBookmark:GURL("https://www.foo.com") withTitle:@"foo"]; // Sign in to sync, after a bookmark has been added. @@ -155,12 +148,7 @@ // Tests that a bookmark added on the client is uploaded to the Sync server. // TODO(crbug.com/814990): Reenable the test. -#if TARGET_IPHONE_SIMULATOR -#define MAYBE_testSyncUploadBookmark FLAKY_testSyncUploadBookmark -#else -#define MAYBE_testSyncUploadBookmark testSyncUploadBookmark -#endif -- (void)MAYBE_testSyncUploadBookmark { +- (void)FLAKY_testSyncUploadBookmark { ChromeIdentity* identity = [SigninEarlGreyUtils fakeIdentity1]; ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()->AddIdentity( identity); @@ -175,12 +163,7 @@ // Tests that a bookmark injected in the FakeServer is synced down to the // client. // TODO(crbug.com/814990): Reenable the test. -#if TARGET_IPHONE_SIMULATOR -#define MAYBE_testSyncDownloadBookmark FLAKY_testSyncDownloadBookmark -#else -#define MAYBE_testSyncDownloadBookmark testSyncDownloadBookmark -#endif -- (void)MAYBE_testSyncDownloadBookmark { +- (void)FLAKY_testSyncDownloadBookmark { [[self class] assertBookmarksWithTitle:@"hoo" expectedCount:0]; chrome_test_util::InjectBookmarkOnFakeSyncServer("http://www.hoo.com", "hoo"); @@ -282,7 +265,14 @@ } // Tests that autofill profile injected in FakeServer gets synced to client. -- (void)testSyncDownloadAutofillProfile { +// TODO(crbug.com/814990): Reenable the test. +#if TARGET_IPHONE_SIMULATOR +#define MAYBE_testSyncDownloadAutofillProfile testSyncDownloadAutofillProfile +#else +#define MAYBE_testSyncDownloadAutofillProfile \ + FLAKY_testSyncDownloadAutofillProfile +#endif +- (void)MAYBE_testSyncDownloadAutofillProfile { const std::string kGuid = "2340E83B-5BEE-4560-8F95-5914EF7F539E"; const std::string kFullName = "Peter Pan"; GREYAssertFalse(chrome_test_util::IsAutofillProfilePresent(kGuid, kFullName), @@ -308,12 +298,7 @@ // Test that update to autofill profile injected in FakeServer gets synced to // client. // TODO(crbug.com/814990): Reenable the test. -#if TARGET_IPHONE_SIMULATOR -#define MAYBE_testSyncUpdateAutofillProfile FLAKY_testSyncUpdateAutofillProfile -#else -#define MAYBE_testSyncUpdateAutofillProfile testSyncUpdateAutofillProfile -#endif -- (void)MAYBE_testSyncUpdateAutofillProfile { +- (void)FLAKY_testSyncUpdateAutofillProfile { const std::string kGuid = "2340E83B-5BEE-4560-8F95-5914EF7F539E"; const std::string kFullName = "Peter Pan"; const std::string kUpdatedFullName = "Roger Rabbit"; @@ -358,12 +343,7 @@ // Test that autofill profile deleted from FakeServer gets deleted from client // as well. // TODO(crbug.com/814990): Reenable the test. -#if TARGET_IPHONE_SIMULATOR -#define MAYBE_testSyncDeleteAutofillProfile FLAKY_testSyncDeleteAutofillProfile -#else -#define MAYBE_testSyncDeleteAutofillProfile testSyncDeleteAutofillProfile -#endif -- (void)MAYBE_testSyncDeleteAutofillProfile { +- (void)FLAKY_testSyncDeleteAutofillProfile { const std::string kGuid = "2340E83B-5BEE-4560-8F95-5914EF7F539E"; const std::string kFullName = "Peter Pan"; GREYAssertFalse(chrome_test_util::IsAutofillProfilePresent(kGuid, kFullName), @@ -398,12 +378,7 @@ // Tests that tabs opened on this client are committed to the Sync server and // that the created sessions entities are correct. // TODO(crbug.com/814990): Reenable the test. -#if TARGET_IPHONE_SIMULATOR -#define MAYBE_testSyncUploadOpenTabs FLAKY_testSyncUploadOpenTabs -#else -#define MAYBE_testSyncUploadOpenTabs testSyncUploadOpenTabs -#endif -- (void)MAYBE_testSyncUploadOpenTabs { +- (void)FLAKY_testSyncUploadOpenTabs { // Create map of canned responses and set up the test HTML server. const GURL URL1 = web::test::HttpServer::MakeUrl("http://page1"); const GURL URL2 = web::test::HttpServer::MakeUrl("http://page2"); @@ -438,12 +413,7 @@ // Tests that a typed URL (after Sync is enabled) is uploaded to the Sync // server. // TODO(crbug.com/814990): Reenable the test. -#if TARGET_IPHONE_SIMULATOR -#define MAYBE_testSyncTypedURLUpload FLAKY_testSyncTypedURLUpload -#else -#define MAYBE_testSyncTypedURLUpload testSyncTypedURLUpload -#endif -- (void)MAYBE_testSyncTypedURLUpload { +- (void)FLAKY_testSyncTypedURLUpload { const GURL mockURL("http://not-a-real-site/"); GREYAssertTrue(chrome_test_util::ClearBrowsingHistory(), @@ -483,12 +453,7 @@ // Tests that typed url is downloaded from sync server. // TODO(crbug.com/814990): Reenable the test. -#if TARGET_IPHONE_SIMULATOR -#define MAYBE_testSyncTypedUrlDownload FLAKY_testSyncTypedUrlDownload -#else -#define MAYBE_testSyncTypedUrlDownload testSyncTypedUrlDownload -#endif -- (void)MAYBE_testSyncTypedUrlDownload { +- (void)FLAKY_testSyncTypedUrlDownload { const GURL mockURL("http://not-a-real-site/"); GREYAssertTrue(chrome_test_util::ClearBrowsingHistory(), @@ -526,13 +491,7 @@ // Tests that when typed url is deleted on the client, sync the change gets // propagated to server. // TODO(crbug.com/814990): Reenable the test. -#if TARGET_IPHONE_SIMULATOR -#define MAYBE_testSyncTypedURLDeleteFromClient \ - FLAKY_testSyncTypedURLDeleteFromClient -#else -#define MAYBE_testSyncTypedURLDeleteFromClient testSyncTypedURLDeleteFromClient -#endif -- (void)MAYBE_testSyncTypedURLDeleteFromClient { +- (void)FLAKY_testSyncTypedURLDeleteFromClient { const GURL mockURL("http://not-a-real-site/"); GREYAssertTrue(chrome_test_util::ClearBrowsingHistory(), @@ -581,13 +540,7 @@ // Test that typed url is deleted from client after server sends tombstone for // that typed url. // TODO(crbug.com/814990): Reenable the test. -#if TARGET_IPHONE_SIMULATOR -#define MAYBE_testSyncTypedURLDeleteFromServer \ - FLAKY_testSyncTypedURLDeleteFromServer -#else -#define MAYBE_testSyncTypedURLDeleteFromServer testSyncTypedURLDeleteFromServer -#endif -- (void)MAYBE_testSyncTypedURLDeleteFromServer { +- (void)FLAKY_testSyncTypedURLDeleteFromServer { const GURL mockURL("http://not-a-real-site/"); GREYAssertTrue(chrome_test_util::ClearBrowsingHistory(),
diff --git a/ios/chrome/browser/ui/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/BUILD.gn index cf1daa40..d2526ab 100644 --- a/ios/chrome/browser/ui/tab_grid/BUILD.gn +++ b/ios/chrome/browser/ui/tab_grid/BUILD.gn
@@ -58,7 +58,6 @@ "tab_grid_top_toolbar.mm", "tab_grid_transition_handler.h", "tab_grid_transition_handler.mm", - "tab_grid_transition_state_provider.h", "tab_grid_view_controller.h", "tab_grid_view_controller.mm", "top_aligned_image_view.h",
diff --git a/ios/chrome/browser/ui/tab_grid/grid_cell.h b/ios/chrome/browser/ui/tab_grid/grid_cell.h index 0399e21..9778ed2 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_cell.h +++ b/ios/chrome/browser/ui/tab_grid/grid_cell.h
@@ -30,6 +30,11 @@ @property(nonatomic, weak) UIImage* icon; @property(nonatomic, weak) UIImage* snapshot; @property(nonatomic, copy) NSString* title; + +// Returns a cell with the same theme, icon, snapshot, and title as the reciever +// (but no delegate or identifier) for use in animated transitions. +- (GridCell*)proxyForTransitions; + @end #endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_CELL_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_cell.mm b/ios/chrome/browser/ui/tab_grid/grid_cell.mm index 86db00e..0b5a891 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_cell.mm +++ b/ios/chrome/browser/ui/tab_grid/grid_cell.mm
@@ -176,6 +176,16 @@ _title = title; } +- (GridCell*)proxyForTransitions { + GridCell* proxy = [[[self class] alloc] initWithFrame:self.bounds]; + proxy.selected = NO; + proxy.theme = self.theme; + proxy.icon = self.icon; + proxy.snapshot = self.snapshot; + proxy.title = self.title; + return proxy; +} + #pragma mark - Private // Sets up the top bar with icon, title, and close button.
diff --git a/ios/chrome/browser/ui/tab_grid/grid_view_controller.h b/ios/chrome/browser/ui/tab_grid/grid_view_controller.h index f34e714..7f2bb0b37 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_view_controller.h +++ b/ios/chrome/browser/ui/tab_grid/grid_view_controller.h
@@ -11,6 +11,7 @@ #import "ios/chrome/browser/ui/tab_grid/grid_theme.h" @protocol GridImageDataSource; +@class GridTransitionLayout; @class GridViewController; // Protocol used to relay relevant user interactions from a grid UI. @@ -45,6 +46,13 @@ @property(nonatomic, weak) id<GridViewControllerDelegate> delegate; // Data source for images. @property(nonatomic, weak) id<GridImageDataSource> imageDataSource; +// YES if the selected cell is visible in the grid. +@property(nonatomic, readonly, getter=isSelectedCellVisible) + BOOL selectedCellVisible; + +// Returns the layout of the grid for use in an animated transition. +- (GridTransitionLayout*)transitionLayout; + @end #endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm index 3f9a9e53..b32d0e5c 100644 --- a/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_grid/grid_view_controller.mm
@@ -4,15 +4,14 @@ #import "ios/chrome/browser/ui/tab_grid/grid_view_controller.h" -#import "base/ios/block_types.h" #import "base/mac/foundation_util.h" #import "base/numerics/safe_conversions.h" -#include "ios/chrome/browser/procedural_block_types.h" #import "ios/chrome/browser/ui/tab_grid/grid_cell.h" #import "ios/chrome/browser/ui/tab_grid/grid_constants.h" #import "ios/chrome/browser/ui/tab_grid/grid_image_data_source.h" #import "ios/chrome/browser/ui/tab_grid/grid_item.h" #import "ios/chrome/browser/ui/tab_grid/grid_layout.h" +#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -106,6 +105,39 @@ return self.items.count == 0; } +- (BOOL)isSelectedCellVisible { + if (self.collectionView.indexPathsForSelectedItems.count == 0) + return NO; + return [self.collectionView.indexPathsForVisibleItems + containsObject:self.collectionView.indexPathsForSelectedItems + .firstObject]; +} + +- (GridTransitionLayout*)transitionLayout { + [self.collectionView layoutIfNeeded]; + NSMutableArray<GridTransitionLayoutItem*>* items = + [[NSMutableArray alloc] init]; + GridTransitionLayoutItem* selectedItem; + for (NSIndexPath* path in self.collectionView.indexPathsForVisibleItems) { + GridCell* cell = base::mac::ObjCCastStrict<GridCell>( + [self.collectionView cellForItemAtIndexPath:path]); + UICollectionViewLayoutAttributes* attributes = + [self.collectionView layoutAttributesForItemAtIndexPath:path]; + // Normalize frame to window coordinates. The attributes class applies this + // change to the other properties such as center, bounds, etc. + attributes.frame = + [self.collectionView convertRect:attributes.frame toView:nil]; + GridTransitionLayoutItem* item = + [GridTransitionLayoutItem itemWithCell:[cell proxyForTransitions] + attributes:attributes]; + [items addObject:item]; + if (cell.selected) { + selectedItem = item; + } + } + return [GridTransitionLayout layoutWithItems:items selectedItem:selectedItem]; +} + #pragma mark - UICollectionViewDataSource - (NSInteger)collectionView:(UICollectionView*)collectionView @@ -174,7 +206,7 @@ - (void)insertItem:(GridItem*)item atIndex:(NSUInteger)index selectedIndex:(NSUInteger)selectedIndex { - ProceduralBlock performDataSourceUpdates = ^{ + auto performDataSourceUpdates = ^{ [self.items insertObject:item atIndex:index]; self.selectedIndex = selectedIndex; }; @@ -182,16 +214,16 @@ performDataSourceUpdates(); return; } - ProceduralBlock performAllUpdates = ^{ + auto performAllUpdates = ^{ performDataSourceUpdates(); self.collectionView.backgroundView.hidden = YES; [self.collectionView insertItemsAtIndexPaths:@[ CreateIndexPath(index) ]]; + }; + auto completion = ^(BOOL finished) { [self.collectionView selectItemAtIndexPath:CreateIndexPath(selectedIndex) animated:YES scrollPosition:UICollectionViewScrollPositionNone]; - }; - ProceduralBlockWithBool completion = ^(BOOL finished) { if (self.items.count == 1) { [self.delegate firstItemWasAddedInGridViewController:self]; } @@ -202,7 +234,7 @@ - (void)removeItemAtIndex:(NSUInteger)index selectedIndex:(NSUInteger)selectedIndex { - ProceduralBlock performDataSourceUpdates = ^{ + auto performDataSourceUpdates = ^{ [self.items removeObjectAtIndex:index]; self.selectedIndex = selectedIndex; }; @@ -210,18 +242,17 @@ performDataSourceUpdates(); return; } - ProceduralBlock performAllUpdates = ^{ + auto performAllUpdates = ^{ performDataSourceUpdates(); [self.collectionView deleteItemsAtIndexPaths:@[ CreateIndexPath(index) ]]; + }; + auto completion = ^(BOOL finished) { if (self.items.count > 0) { [self.collectionView selectItemAtIndexPath:CreateIndexPath(selectedIndex) animated:YES scrollPosition:UICollectionViewScrollPositionNone]; - } - }; - ProceduralBlockWithBool completion = ^(BOOL finished) { - if (self.items.count == 0) { + } else { self.collectionView.backgroundView.hidden = NO; [self.delegate lastItemWasClosedInGridViewController:self]; } @@ -250,7 +281,7 @@ - (void)moveItemFromIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex selectedIndex:(NSUInteger)selectedIndex { - ProceduralBlock performDataSourceUpdates = ^{ + auto performDataSourceUpdates = ^{ GridItem* item = self.items[fromIndex]; [self.items removeObjectAtIndex:fromIndex]; [self.items insertObject:item atIndex:toIndex]; @@ -260,16 +291,19 @@ performDataSourceUpdates(); return; } - ProceduralBlock performAllUpdates = ^{ + auto performAllUpdates = ^{ performDataSourceUpdates(); [self.collectionView moveItemAtIndexPath:CreateIndexPath(fromIndex) toIndexPath:CreateIndexPath(toIndex)]; + }; + auto completion = ^(BOOL finished) { [self.collectionView selectItemAtIndexPath:CreateIndexPath(selectedIndex) animated:YES scrollPosition:UICollectionViewScrollPositionNone]; }; - [self.collectionView performBatchUpdates:performAllUpdates completion:nil]; + [self.collectionView performBatchUpdates:performAllUpdates + completion:completion]; } #pragma mark - Private
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm index 36125dc..1057c34 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -85,6 +85,7 @@ [[TabGridViewController alloc] init]; self.transitionHandler = [[TabGridTransitionHandler alloc] init]; self.transitionHandler.provider = mainViewController; + mainViewController.modalPresentationStyle = UIModalPresentationCustom; mainViewController.transitioningDelegate = self.transitionHandler; mainViewController.tabPresentationDelegate = self; _mainViewController = mainViewController;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.h b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.h index bc04bb1..38b57dca 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.h +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.h
@@ -7,12 +7,12 @@ #import <UIKit/UIKit.h> -@protocol TabGridTransitionStateProvider; +@protocol GridTransitionStateProviding; @interface TabGridTransitionHandler : NSObject<UIViewControllerTransitioningDelegate> -@property(nonatomic, weak) id<TabGridTransitionStateProvider> provider; +@property(nonatomic, weak) id<GridTransitionStateProviding> provider; @end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm index 6582ec35..b1b15d9 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm
@@ -4,9 +4,9 @@ #import "ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.h" -#import "ios/chrome/browser/ui/tab_grid/tab_grid_transition_state_provider.h" #import "ios/chrome/browser/ui/tab_grid/transitions/grid_to_hidden_tab_animator.h" #import "ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.h" +#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h" #import "ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -24,7 +24,7 @@ presentingController:(UIViewController*)presenting sourceController:(UIViewController*)source { id<UIViewControllerAnimatedTransitioning> animator; - if (self.provider.selectedTabVisible) { + if (self.provider.selectedCellVisible) { // This will be a GridToVisibleTabAnimator eventually. animator = [[GridToHiddenTabAnimator alloc] init]; } else { @@ -35,8 +35,7 @@ - (id<UIViewControllerAnimatedTransitioning>) animationControllerForDismissedController:(UIViewController*)dismissed { - // This will be a TabToGridAnimator eventually. - return nil; + return [[TabToGridAnimator alloc] initWithStateProvider:self.provider]; } @end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_state_provider.h b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_state_provider.h deleted file mode 100644 index 7ee09fb..0000000 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_state_provider.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_TRANSITION_STATE_PROVIDER_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_TRANSITION_STATE_PROVIDER_H_ - -#import <Foundation/Foundation.h> - -// Objects conforming to this protocol can provide state information to -// transition delegates and animators for the tab grid. -@protocol TabGridTransitionStateProvider - -// YES if the currently selected tab is visible in the tab grid. -@property(nonatomic, readonly) BOOL selectedTabVisible; - -@end - -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_TRANSITION_STATE_PROVIDER_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h index 0f9882f7..50d4734c 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h
@@ -8,7 +8,7 @@ #import <UIKit/UIKit.h> #import "ios/chrome/browser/ui/tab_grid/tab_grid_paging.h" -#import "ios/chrome/browser/ui/tab_grid/tab_grid_transition_state_provider.h" +#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h" @protocol GridConsumer; @protocol GridCommands; @@ -25,10 +25,10 @@ - (void)showActiveTab; @end -// View controller representing a tab switcher. The tab switcher has an +// View controller representing a tab switcher. The tab switcher has an // incognito tab grid, regular tab grid, and remote tabs. @interface TabGridViewController - : UIViewController<TabGridPaging, TabGridTransitionStateProvider> + : UIViewController<TabGridPaging, GridTransitionStateProviding> // Delegate for this view controller to handle presenting tab UI. @property(nonatomic, weak) id<TabPresentationDelegate> tabPresentationDelegate;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm index 6c8bfe3..ab798ea 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -33,6 +33,7 @@ @property(nonatomic, weak) TabGridBottomToolbar* bottomToolbar; @property(nonatomic, weak) UIButton* closeAllButton; @property(nonatomic, weak) UIButton* doneButton; +@property(nonatomic, weak) UIButton* createTabButton; @property(nonatomic, weak) UIButton* floatingButton; @end @@ -55,6 +56,7 @@ @synthesize bottomToolbar = _bottomToolbar; @synthesize closeAllButton = _closeAllButton; @synthesize doneButton = _doneButton; +@synthesize createTabButton = _createTabButton; @synthesize floatingButton = _floatingButton; - (instancetype)init { @@ -75,16 +77,16 @@ [self setupRegularTabsViewController]; [self setupRemoteTabsViewController]; [self setupTopToolbar]; - [self setupTopToolbarButtons]; [self setupBottomToolbar]; - [self setupBottomToolbarButtons]; + [self setupFloatingButton]; } - (void)viewWillAppear:(BOOL)animated { // Call the current page setter to sync the scroll view offset to the current // page value. self.currentPage = _currentPage; - [self updateDoneAndCloseAllButtons]; + [self updateToolbarsForCurrentSizeClass]; + [self enableButtonsForCurrentPage]; if (animated && self.transitionCoordinator) { [self animateToolbarsForAppearance]; } @@ -124,7 +126,7 @@ float fractionalPage = scrollView.contentOffset.x / pageWidth; NSUInteger page = lround(fractionalPage); _currentPage = static_cast<TabGridPage>(page); - [self updateDoneAndCloseAllButtons]; + [self enableButtonsForCurrentPage]; } #pragma mark - UIScrollViewAccessibilityDelegate @@ -142,10 +144,39 @@ } } -#pragma mark - TabGridTransitionStateProvider properties +#pragma mark - GridTransitionStateProviding properties -- (BOOL)selectedTabVisible { - return NO; +- (BOOL)isSelectedCellVisible { + switch (self.currentPage) { + case TabGridPageIncognitoTabs: + return self.incognitoTabsViewController.selectedCellVisible; + case TabGridPageRegularTabs: + return self.regularTabsViewController.selectedCellVisible; + case TabGridPageRemoteTabs: + return NO; + } +} + +- (GridTransitionLayout*)layoutForTransitionContext: + (id<UIViewControllerContextTransitioning>)context { + switch (self.currentPage) { + case TabGridPageIncognitoTabs: + return [self.incognitoTabsViewController transitionLayout]; + case TabGridPageRegularTabs: + return [self.regularTabsViewController transitionLayout]; + case TabGridPageRemoteTabs: + return nil; + } +} + +- (UIView*)proxyContainerForTransitionContext: + (id<UIViewControllerContextTransitioning>)context { + return self.view; +} + +- (UIView*)proxyPositionForTransitionContext: + (id<UIViewControllerContextTransitioning>)context { + return self.scrollView; } #pragma mark - Public @@ -417,74 +448,104 @@ } } -// Adds the top toolbar buttons. -- (void)setupTopToolbarButtons { +// Adds floating button and constraints. +- (void)setupFloatingButton { + UIButton* button = [UIButton buttonWithType:UIButtonTypeSystem]; + button.translatesAutoresizingMaskIntoConstraints = NO; + // TODO(crbug.com/818198) : Replace with assets. + button.backgroundColor = [UIColor whiteColor]; + button.layer.cornerRadius = 22.0f; + button.layer.masksToBounds = YES; + [self.view addSubview:button]; + self.floatingButton = button; + NSArray* constraints = @[ + [button.widthAnchor constraintEqualToConstant:44.0f], + [button.heightAnchor constraintEqualToConstant:44.0f], + [button.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor + constant:-10.0f], + [button.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor + constant:-10.0f] + ]; + [NSLayoutConstraint activateConstraints:constraints]; +} + +// Sets visibility of toolbars and floating button in the arrangement containing +// the floating button. Also updates |self.doneButton|, |self.closeAllButton|, +// and |self.createTabButton| to the visible button. +- (void)configureToolbarsWithFloatingButton { + self.topToolbar.leadingButton.hidden = NO; + self.topToolbar.trailingButton.hidden = NO; + self.bottomToolbar.hidden = YES; + self.floatingButton.hidden = NO; self.doneButton = self.topToolbar.leadingButton; self.closeAllButton = self.topToolbar.trailingButton; - self.doneButton.accessibilityIdentifier = kTabGridDoneButtonAccessibilityID; + self.createTabButton = self.floatingButton; +} + +// Sets visibility of toolbars and floating button in the arrangement that +// includes the bottom toolbar. Also updates |self.doneButton|, +// |self.closeAllButton|, and |self.createTabButton| to the visible button. +- (void)configureToolbarsWithBottomToolbar { + self.topToolbar.leadingButton.hidden = YES; + self.topToolbar.trailingButton.hidden = YES; + self.bottomToolbar.hidden = NO; + self.floatingButton.hidden = YES; + self.doneButton = self.bottomToolbar.leadingButton; + self.closeAllButton = self.bottomToolbar.trailingButton; + self.createTabButton = self.bottomToolbar.roundButton; +} + +// Call this method whenever |self.doneButton|, |self.closeAllButton|, or +// |self.createTabButton| is updated. +- (void)resetButtonLabelsAndActions { // TODO(crbug.com/818699) : Localize strings. [self.doneButton setTitle:@"Done" forState:UIControlStateNormal]; [self.closeAllButton setTitle:@"Close All" forState:UIControlStateNormal]; + self.doneButton.accessibilityIdentifier = kTabGridDoneButtonAccessibilityID; [self.doneButton addTarget:self action:@selector(doneButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; [self.closeAllButton addTarget:self action:@selector(closeAllButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; + [self.createTabButton addTarget:self + action:@selector(createTabButtonTapped:) + forControlEvents:UIControlEventTouchUpInside]; } -// Adds the bottom toolbar buttons. -- (void)setupBottomToolbarButtons { - // TODO(crbug.com/818699) : Localize strings. - [self.bottomToolbar.leadingButton setTitle:@"Done" - forState:UIControlStateNormal]; - [self.bottomToolbar.trailingButton setTitle:@"Close All" - forState:UIControlStateNormal]; - [self.bottomToolbar.roundButton setTitle:@"New" - forState:UIControlStateNormal]; - [self.bottomToolbar.leadingButton addTarget:self - action:@selector(doneButtonTapped:) - forControlEvents:UIControlEventTouchUpInside]; - [self.bottomToolbar.trailingButton addTarget:self - action:@selector(closeAllButtonTapped:) - forControlEvents:UIControlEventTouchUpInside]; - [self.bottomToolbar.roundButton addTarget:self - action:@selector(newTabButtonTapped:) - forControlEvents:UIControlEventTouchUpInside]; -} - -// Translates the toolbar views offscreen and then animates them back in using -// the transition coordinator. Transitions are preferred here since they don't -// interact with the layout system at all. -- (void)animateToolbarsForAppearance { - DCHECK(self.transitionCoordinator); - // Capture the current toolbar transforms. - CGAffineTransform topToolbarBaseTransform = self.topToolbar.transform; - CGAffineTransform bottomToolbarBaseTransform = self.bottomToolbar.transform; - // Translate the top toolbar up offscreen by shifting it up by its height. - self.topToolbar.transform = - CGAffineTransformTranslate(self.topToolbar.transform, /*tx=*/0, - /*ty=*/-self.topToolbar.bounds.size.height); - // Translate the bottom toolbar down offscreen by shifting it down by its - // height. - self.bottomToolbar.transform = - CGAffineTransformTranslate(self.bottomToolbar.transform, /*tx=*/0, - /*ty=*/self.topToolbar.bounds.size.height); - // Block that restores the toolbar transforms, suitable for using with the - // transition coordinator. - void (^animation)(id<UIViewControllerTransitionCoordinatorContext>) = - ^(id<UIViewControllerTransitionCoordinatorContext> context) { - self.topToolbar.transform = topToolbarBaseTransform; - self.bottomToolbar.transform = bottomToolbarBaseTransform; - }; - // Animate the toolbars into place alongside the current transition by - // restoring their transforms. - [self.transitionCoordinator animateAlongsideTransition:animation - completion:nil]; +// Sets up the toolbars and buttons based on size class. +- (void)updateToolbarsForCurrentSizeClass { + if (self.traitCollection.verticalSizeClass == + UIUserInterfaceSizeClassCompact) { + // When the vertical size is limited, we don't want a bottom toolbar. + [self configureToolbarsWithFloatingButton]; + [self resetButtonLabelsAndActions]; + return; + } + switch (self.traitCollection.horizontalSizeClass) { + case UIUserInterfaceSizeClassCompact: + // The UI is vertically long and narrow so include a bottom toolbar. + [self configureToolbarsWithBottomToolbar]; + [self resetButtonLabelsAndActions]; + break; + case UIUserInterfaceSizeClassRegular: + // The UI is wide and long and looks best with a FAB. + [self configureToolbarsWithFloatingButton]; + // There is enough space for the tab view to have a tab strip, + // so put the done button on the trailing side where the tab + // switcher button is located on the tab view. + self.doneButton = self.topToolbar.trailingButton; + self.closeAllButton = self.topToolbar.leadingButton; + [self resetButtonLabelsAndActions]; + break; + case UIUserInterfaceSizeClassUnspecified: + NOTREACHED() << "Invalid size class."; + break; + } } // Update |enabled| property of the done and close all buttons. -- (void)updateDoneAndCloseAllButtons { +- (void)enableButtonsForCurrentPage { switch (self.currentPage) { case TabGridPageIncognitoTabs: self.doneButton.enabled = !self.incognitoTabsViewController.isGridEmpty; @@ -501,6 +562,45 @@ } } +// Translates the toolbar views offscreen and then animates them back in using +// the transition coordinator. Transitions are preferred here since they don't +// interact with the layout system at all. +- (void)animateToolbarsForAppearance { + DCHECK(self.transitionCoordinator); + // TODO(crbug.com/820410): Tune the timing of these animations. + + // Capture the current toolbar transforms. + CGAffineTransform topToolbarBaseTransform = self.topToolbar.transform; + CGAffineTransform bottomToolbarBaseTransform = self.bottomToolbar.transform; + // Translate the top toolbar up offscreen by shifting it up by its height. + self.topToolbar.transform = CGAffineTransformTranslate( + self.topToolbar.transform, /*tx=*/0, + /*ty=*/-(self.topToolbar.bounds.size.height * 0.5)); + // Translate the bottom toolbar down offscreen by shifting it down by its + // height. + self.bottomToolbar.transform = CGAffineTransformTranslate( + self.bottomToolbar.transform, /*tx=*/0, + /*ty=*/(self.topToolbar.bounds.size.height * 0.5)); + + // Block that restores the toolbar transforms, suitable for using with the + // transition coordinator. + auto animation = ^(id<UIViewControllerTransitionCoordinatorContext> context) { + self.topToolbar.transform = topToolbarBaseTransform; + self.bottomToolbar.transform = bottomToolbarBaseTransform; + }; + + // Also hide the scroll view (and thus the tab grids) until the transition + // completes. + self.scrollView.hidden = YES; + auto cleanup = ^(id<UIViewControllerTransitionCoordinatorContext> context) { + self.scrollView.hidden = NO; + }; + + // Animate the toolbars into place alongside the current transition. + [self.transitionCoordinator animateAlongsideTransition:animation + completion:cleanup]; +} + #pragma mark - GridViewControllerDelegate - (void)gridViewController:(GridViewController*)gridViewController @@ -524,12 +624,12 @@ - (void)lastItemWasClosedInGridViewController: (GridViewController*)gridViewController { - [self updateDoneAndCloseAllButtons]; + [self enableButtonsForCurrentPage]; } - (void)firstItemWasAddedInGridViewController: (GridViewController*)gridViewController { - [self updateDoneAndCloseAllButtons]; + [self enableButtonsForCurrentPage]; } #pragma mark - Button actions @@ -552,7 +652,7 @@ } } -- (void)newTabButtonTapped:(id)sender { +- (void)createTabButtonTapped:(id)sender { switch (self.currentPage) { case TabGridPageIncognitoTabs: [self.incognitoTabsDelegate addNewItem];
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/BUILD.gn b/ios/chrome/browser/ui/tab_grid/transitions/BUILD.gn index 729b2529..52ed4990a 100644 --- a/ios/chrome/browser/ui/tab_grid/transitions/BUILD.gn +++ b/ios/chrome/browser/ui/tab_grid/transitions/BUILD.gn
@@ -10,6 +10,9 @@ "grid_to_hidden_tab_animator.mm", "grid_to_visible_tab_animator.h", "grid_to_visible_tab_animator.mm", + "grid_transition_layout.h", + "grid_transition_layout.mm", + "grid_transition_state_providing.h", "tab_to_grid_animator.h", "tab_to_grid_animator.mm", ]
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h new file mode 100644 index 0000000..c8de9ee3 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h
@@ -0,0 +1,57 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_GRID_TRANSITION_LAYOUT_H_ +#define IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_GRID_TRANSITION_LAYOUT_H_ + +#import <UIKit/UIKit.h> + +@class GridTransitionLayoutItem; + +// An encapsulation of information for the layout of a grid of cells that will +// be used in an animated transition. The layout object is composed of layout +// items (see below). +@interface GridTransitionLayout : NSObject + +// All of the items in the layout. +@property(nonatomic, copy, readonly) NSArray<GridTransitionLayoutItem*>* items; +// The item in the layout (if any) that's selected. +// Note that |selectedItem.cell.selected| doesn't need to be YES; the transition +// animation may set or unset that selection state as part of the animation. +@property(nonatomic, strong, readonly) GridTransitionLayoutItem* selectedItem; + +// Creates a new layout object with |items|, and |selectedItem| selected. +// |items| should be non-nil, but it may be empty. +// |selectedItem| must either be nil, or one of the members of |items|. ++ (instancetype)layoutWithItems:(NSArray<GridTransitionLayoutItem*>*)items + selectedItem:(GridTransitionLayoutItem*)selectedItem; + +@end + +// An encapsulation of information for the layout of a single grid cell, in the +// form of UICollectionView classes. +@interface GridTransitionLayoutItem : NSObject + +// A cell object with the desired appearance for the animation. This should +// correspond to an actual cell in the collection view involved in the trans- +// ition, but the value of thie property should not be in any view hierarchy +// when the layout item is created. +@property(nonatomic, strong, readonly) UICollectionViewCell* cell; +// The layout attributes for the cell in the collection view, normalized to +// UIWindow coordinates. It's the responsibility of the setter to do this +// normalization. +@property(nonatomic, strong, readonly) + UICollectionViewLayoutAttributes* attributes; + +// Creates a new layout item instance will |cell| and |attributes|, neither of +// which can be nil. +// It's an error if |cell| has a superview. +// The properties (size, etc) of |attributes| don't need to match the corres- +// ponding properties of |cell| when the item is created. ++ (instancetype)itemWithCell:(UICollectionViewCell*)cell + attributes:(UICollectionViewLayoutAttributes*)attributes; + +@end + +#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_GRID_TRANSITION_LAYOUT_H_
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.mm b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.mm new file mode 100644 index 0000000..26d5256 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.mm
@@ -0,0 +1,58 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#include "base/logging.h" + +@interface GridTransitionLayout () +@property(nonatomic, readwrite) NSArray<GridTransitionLayoutItem*>* items; +@property(nonatomic, readwrite) GridTransitionLayoutItem* selectedItem; +@end + +@implementation GridTransitionLayout +@synthesize selectedItem = _selectedItem; +@synthesize items = _items; + ++ (instancetype)layoutWithItems:(NSArray<GridTransitionLayoutItem*>*)items + selectedItem:(GridTransitionLayoutItem*)selectedItem { + DCHECK(items); + GridTransitionLayout* layout = [[GridTransitionLayout alloc] init]; + layout.items = items; + layout.selectedItem = selectedItem; + return layout; +} + +- (void)setSelectedItem:(GridTransitionLayoutItem*)selectedItem { + DCHECK([self.items containsObject:selectedItem]); + _selectedItem = selectedItem; +} + +@end + +@interface GridTransitionLayoutItem () +@property(nonatomic, readwrite) UICollectionViewCell* cell; +@property(nonatomic, readwrite) UICollectionViewLayoutAttributes* attributes; +@end + +@implementation GridTransitionLayoutItem +@synthesize cell = _cell; +@synthesize attributes = _attributes; + ++ (instancetype)itemWithCell:(UICollectionViewCell*)cell + attributes:(UICollectionViewLayoutAttributes*)attributes { + DCHECK(cell); + DCHECK(attributes); + DCHECK(!cell.superview); + GridTransitionLayoutItem* item = [[GridTransitionLayoutItem alloc] init]; + item.cell = cell; + item.attributes = attributes; + return item; +} + +@end
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h new file mode 100644 index 0000000..5e1de24 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h
@@ -0,0 +1,39 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_GRID_TRANSITION_STATE_PROVIDING_H_ +#define IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_GRID_TRANSITION_STATE_PROVIDING_H_ + +#import <Foundation/Foundation.h> + +@class GridTransitionLayout; + +// Objects conforming to this protocol can provide state information to +// transition delegates and animators for a grid. +@protocol GridTransitionStateProviding + +// YES if the currently selected cell is visible in the grid. +@property(nonatomic, readonly, getter=isSelectedCellVisible) + BOOL selectedCellVisible; + +// Asks the provider for an aray of layout items that provide objects for use +// in building an animated transition. +- (GridTransitionLayout*)layoutForTransitionContext: + (id<UIViewControllerContextTransitioning>)context; + +// Asks the provider for the view to add proxy views to when building an +// animated transition. +- (UIView*)proxyContainerForTransitionContext: + (id<UIViewControllerContextTransitioning>)context; + +// Asks the provider for the view (if any) that proxy views should be added +// in front of when building an animated transition. It's an error if this +// view is not nil and isn't an immediate subview of the view returned by +// |-proxyContainerForTransitionContext:| +- (UIView*)proxyPositionForTransitionContext: + (id<UIViewControllerContextTransitioning>)context; + +@end + +#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_TAB_GRID_TRANSITION_STATE_PROVIDING_H_
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.h b/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.h index 1c4b9da..b13f238 100644 --- a/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.h +++ b/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.h
@@ -7,8 +7,17 @@ #import <UIKit/UIKit.h> +@protocol GridTransitionStateProviding; + +// Animator object for transitioning from a fullscreen view controller (the +// "tab") into a collection view of square-ish items (the "grid"). @interface TabToGridAnimator : NSObject<UIViewControllerAnimatedTransitioning> +// Initialize an animator object with |stateProvider| to provide state +// information for the transition. +- (instancetype)initWithStateProvider: + (id<GridTransitionStateProviding>)stateProvider; + @end #endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_TAB_TO_GRID_ANIMATOR_H_
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm b/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm index 4ca4baf..03b3319 100644 --- a/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm +++ b/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm
@@ -4,19 +4,191 @@ #import "ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.h" +#import "base/logging.h" +#import "base/mac/foundation_util.h" +#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h" +#import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_state_providing.h" + #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif +@interface TabToGridAnimator () +// State provider for this transition. +@property(nonatomic, weak) id<GridTransitionStateProviding> stateProvider; +@end + @implementation TabToGridAnimator +@synthesize stateProvider = _stateProvider; + +- (instancetype)initWithStateProvider: + (id<GridTransitionStateProviding>)stateProvider { + if ((self = [super init])) { + _stateProvider = stateProvider; + } + return self; +} - (NSTimeInterval)transitionDuration: (id<UIViewControllerContextTransitioning>)transitionContext { - return 0.25; + return 0.4; } - (void)animateTransition: (id<UIViewControllerContextTransitioning>)transitionContext { + // Get views and view controllers for this transition. + UIView* containerView = [transitionContext containerView]; + UIViewController* gridViewController = [transitionContext + viewControllerForKey:UITransitionContextToViewControllerKey]; + UIView* gridView = + [transitionContext viewForKey:UITransitionContextToViewKey]; + UIView* dismissingView = + [transitionContext viewForKey:UITransitionContextFromViewKey]; + + // Extract some useful metrics from the tab view. + CGSize proxySize = dismissingView.bounds.size; + CGPoint proxyCenter = dismissingView.center; + + // Add the grid view to the container. This isn't just for the transition; + // this is how the grid view controller's view is added to the view + // hierarchy. + [containerView insertSubview:gridView belowSubview:dismissingView]; + gridView.frame = + [transitionContext finalFrameForViewController:gridViewController]; + + // Get the layout of the grid for the transition. + GridTransitionLayout* layout = + [self.stateProvider layoutForTransitionContext:transitionContext]; + + // Compute the scale of the transition grid (which is at the propotional size + // of the actual tab view. + CGFloat xScale = proxySize.width / layout.selectedItem.attributes.size.width; + CGFloat yScale = + proxySize.height / layout.selectedItem.attributes.size.height; + + // Ask the state provider for the views to use when inserting the tab grid. + UIView* proxyContainer = + [self.stateProvider proxyContainerForTransitionContext:transitionContext]; + UIView* viewBehindProxies = + [self.stateProvider proxyPositionForTransitionContext:transitionContext]; + + // Lay out the transition grid and add it to the view hierarchy. + CGFloat finalSelectedCellCornerRadius = 0.0; + for (GridTransitionLayoutItem* item in layout.items) { + // The state provider vends attributes in UIWindow coordinates. + // Find where this item is located in |proxyContainer|'s coordinate. + CGPoint gridCenter = + [proxyContainer convertPoint:item.attributes.center fromView:nil]; + // Map that to the scale and position of the transition grid. + CGPoint center = CGPointMake( + proxyCenter.x + + ((gridCenter.x - layout.selectedItem.attributes.center.x) * xScale), + proxyCenter.y + + ((gridCenter.y - layout.selectedItem.attributes.center.y) * + yScale)); + UICollectionViewCell* cell = item.cell; + cell.bounds = item.attributes.bounds; + // Add a scale transform to the cell so it matches the x-scale of the + // open tab. + cell.transform = CGAffineTransformScale(cell.transform, xScale, xScale); + cell.center = center; + if (item == layout.selectedItem) { + finalSelectedCellCornerRadius = cell.contentView.layer.cornerRadius; + cell.contentView.layer.cornerRadius = 0.0; + } + // Add the cell into the container for the transition. + [proxyContainer insertSubview:cell aboveSubview:viewBehindProxies]; + } + + // The transition is structured as four separate animations. Three of them + // are timed based on |staggeredDuration|, which is a configurable fraction + // of the overall animation duration. + // (1) Fading out the view being dismissed. This happens during the first 20% + // of the overall animation. + // (2) Zooming the selected cell into position. This starts immediately and + // has a duration of |staggeredDuration|. + // (3) Fading in the selected cell highlight indicator. This starts after a + // delay of |staggeredDuration| and runs to the end of the transition. + // This means it starts as soon as (2) ends. + // (4) Zooming all other cells into position. This ends at the end of the + // transition and has a duration of |staggeredDuration|. + // + // Animation (4) always runs the whole duration of the transition, so it's + // where the completion block that does overall cleanup is run. + + // TODO(crbug.com/804539): Factor all of these animations into a single + // Orchestrator object that the present and dismiss animation can both use. + + // TODO(crbug.com/820410): Tune the timing, relative pacing, and curves of + // these animations. + + NSTimeInterval duration = [self transitionDuration:transitionContext]; + CGFloat staggeredDuration = duration * 0.7; + + // (1) Fade out active tab view. + [UIView animateWithDuration:duration / 5 + animations:^{ + dismissingView.alpha = 0; + } + completion:nil]; + + // (2) Zoom selected cell into place. Also round its corners. + UICollectionViewCell* selectedCell = layout.selectedItem.cell; + [UIView animateWithDuration:staggeredDuration + delay:0.0 + options:UIViewAnimationOptionCurveEaseOut + animations:^{ + selectedCell.center = [containerView + convertPoint:layout.selectedItem.attributes.center + fromView:nil]; + selectedCell.bounds = + layout.selectedItem.attributes.bounds; + selectedCell.transform = CGAffineTransformIdentity; + selectedCell.contentView.layer.cornerRadius = + finalSelectedCellCornerRadius; + } + completion:nil]; + + // (3) Show highlight state on selected cell. + [UIView animateWithDuration:duration - staggeredDuration + delay:staggeredDuration + options:UIViewAnimationOptionCurveEaseIn + animations:^{ + selectedCell.selected = YES; + } + completion:nil]; + + // (4) Zoom other cells into place. + [UIView animateWithDuration:staggeredDuration + delay:duration - staggeredDuration + options:UIViewAnimationOptionCurveEaseOut + animations:^{ + for (GridTransitionLayoutItem* item in layout.items) { + if (item == layout.selectedItem) + continue; + UIView* cell = item.cell; + cell.center = + [containerView convertPoint:item.attributes.center fromView:nil]; + cell.transform = CGAffineTransformIdentity; + } + } + completion:^(BOOL finished) { + // Clean up all of the proxy cells. + for (GridTransitionLayoutItem* item in layout.items) { + [item.cell removeFromSuperview]; + } + // If the transition was cancelled, restore the dismissing view and + // remove the grid view. + // If not, remove the dismissing view. + if (transitionContext.transitionWasCancelled) { + dismissingView.alpha = 1.0; + [gridView removeFromSuperview]; + } else { + [dismissingView removeFromSuperview]; + } + // Mark the transition as completed. + [transitionContext completeTransition:YES]; + }]; } @end
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm index b6a9aa7..f5df865 100644 --- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm +++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm
@@ -149,8 +149,6 @@ - (void)setUpBlurredBackground { UIBlurEffect* blurEffect = self.buttonFactory.toolbarConfiguration.blurEffect; self.blur = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; - self.blur.contentView.backgroundColor = - self.buttonFactory.toolbarConfiguration.blurEffectBackgroundColor; [self addSubview:self.blur]; self.contentView = self;
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm index 260a995..33b489a 100644 --- a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm +++ b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm
@@ -85,9 +85,6 @@ UIBlurEffect* blurEffect = self.buttonFactory.toolbarConfiguration.blurEffect; self.blur = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; - self.blur.contentView.backgroundColor = - self.buttonFactory.toolbarConfiguration.blurEffectBackgroundColor; - [self addSubview:self.blur]; self.blur.translatesAutoresizingMaskIntoConstraints = NO; AddSameConstraints(self.blur, self);
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h index 41eb942..3d21add 100644 --- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h +++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h
@@ -22,9 +22,6 @@ // Blur effect for the toolbar background. @property(nonatomic, readonly) UIBlurEffect* blurEffect; -// Background color for the blur effect view. -@property(nonatomic, readonly) UIColor* blurEffectBackgroundColor; - // Background color of the NTP. Used to do as if the toolbar was transparent and // the NTP is visible behind it. @property(nonatomic, readonly) UIColor* NTPBackgroundColor;
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm index 043786ad..97fb26e1 100644 --- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm +++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm
@@ -35,16 +35,6 @@ } } -- (UIColor*)blurEffectBackgroundColor { - switch (self.style) { - case NORMAL: - return [UIColor colorWithWhite:kBlurBackgroundGrayscaleComponent - alpha:kBlurBackgroundAlpha]; - case INCOGNITO: - return nil; - } -} - - (UIColor*)NTPBackgroundColor { switch (self.style) { case NORMAL:
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm index 2c45c40b5..7ebe34e 100644 --- a/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm +++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm
@@ -340,6 +340,9 @@ CGRect newFrame = oldFrame; newFrame.size.width = width; + if (self.webStateList->GetActiveWebState()) + [self updateToolbarForSnapshot:self.webStateList->GetActiveWebState()]; + self.viewController.view.superview.frame = newFrame; [self.toolbarViewController activateFakeSafeAreaInsets:safeAreaInsets]; [self.viewController.view.superview layoutIfNeeded]; @@ -349,11 +352,17 @@ self.viewController.view.superview.frame = oldFrame; [self.toolbarViewController deactivateFakeSafeAreaInsets]; + if (self.webStateList->GetActiveWebState()) + [self resetToolbarAfterSnapshot]; + return toolbarSnapshotView; } - (UIColor*)toolbarBackgroundColor { - return self.toolbarViewController.backgroundColor; + if (self.webStateList && self.webStateList->GetActiveWebState() && + IsVisibleUrlNewTabPage(self.webStateList->GetActiveWebState())) + return self.toolbarViewController.backgroundColorNTP; + return nil; } #pragma mark - FakeboxFocuser @@ -400,12 +409,12 @@ #pragma mark - SideSwipeToolbarSnapshotProviding - (UIImage*)toolbarSideSwipeSnapshotForWebState:(web::WebState*)webState { - [self updateToolbarForSideSwipeSnapshot:webState]; + [self updateToolbarForSnapshot:webState]; UIImage* toolbarSnapshot = CaptureViewWithOption( [self.viewController view], [[UIScreen mainScreen] scale], kClientSideRendering); - [self resetToolbarAfterSideSwipeSnapshot]; + [self resetToolbarAfterSnapshot]; return toolbarSnapshot; } @@ -483,28 +492,29 @@ // Updates the toolbar so it is in a state where a snapshot for |webState| can // be taken. -- (void)updateToolbarForSideSwipeSnapshot:(web::WebState*)webState { +- (void)updateToolbarForSnapshot:(web::WebState*)webState { BOOL isNTP = IsVisibleUrlNewTabPage(webState); - // Don't do anything for a live non-ntp tab. - if (webState == self.webStateList->GetActiveWebState() && !isNTP) { + self.viewController.view.hidden = NO; + // Don't do anything for the current tab if it is not a non-incognito NTP. + if (webState == self.webStateList->GetActiveWebState() && + !(isNTP && !self.browserState->IsOffTheRecord())) { [self.locationBarCoordinator.view setHidden:NO]; return; } - self.viewController.view.hidden = NO; [self.locationBarCoordinator.view setHidden:YES]; [self.mediator updateConsumerForWebState:webState]; - [self.toolbarViewController updateForSideSwipeSnapshotOnNTP:isNTP]; + [self.toolbarViewController updateForSnapshotOnNTP:isNTP]; } -// Resets the toolbar after taking a side swipe snapshot. After calling this -// method the toolbar is adapted to the current webState. -- (void)resetToolbarAfterSideSwipeSnapshot { +// Resets the toolbar after taking a snapshot. After calling this method the +// toolbar is adapted to the current webState. +- (void)resetToolbarAfterSnapshot { [self.mediator updateConsumerForWebState:self.webStateList->GetActiveWebState()]; [self.locationBarCoordinator.view setHidden:NO]; - [self.toolbarViewController resetAfterSideSwipeSnapshot]; + [self.toolbarViewController resetAfterSnapshot]; } // Animates |_toolbar| and |_locationBarView| for omnibox expansion. If
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.h b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.h index 527ddb1..d21ecd93 100644 --- a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.h +++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.h
@@ -45,8 +45,8 @@ @property(nonatomic, assign) BOOL expanded; // Omnibox focuser. @property(nonatomic, weak) id<OmniboxFocuser> omniboxFocuser; -// Background color of the toolbar. Returns nil if it is the default color. -@property(nonatomic, strong, readonly) UIColor* backgroundColor; +// Background color of the toolbar when presented on the NTP. +@property(nonatomic, strong, readonly) UIColor* backgroundColorNTP; // Sets the location bar view, containing the omnibox. - (void)setLocationBarView:(UIView*)locationBarView; @@ -63,9 +63,9 @@ - (void)addToolbarContractionAnimations:(UIViewPropertyAnimator*)animator; // Updates the view so a snapshot can be taken. It needs to be adapted, // depending on if it is a snapshot displayed |onNTP| or not. -- (void)updateForSideSwipeSnapshotOnNTP:(BOOL)onNTP; -// Resets the view after taking a snapshot for a side swipe. -- (void)resetAfterSideSwipeSnapshot; +- (void)updateForSnapshotOnNTP:(BOOL)onNTP; +// Resets the view after taking a snapshot. +- (void)resetAfterSnapshot; // Sets the background color of the Toolbar to the one of the Incognito NTP, // with an |alpha|. - (void)setBackgroundToIncognitoNTPColorWithAlpha:(CGFloat)alpha;
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm index 056608b..80f0584 100644 --- a/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm +++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_view_controller.mm
@@ -236,7 +236,7 @@ self.expanded = NO; } -- (void)updateForSideSwipeSnapshotOnNTP:(BOOL)onNTP { +- (void)updateForSnapshotOnNTP:(BOOL)onNTP { self.view.progressBar.hidden = YES; if (onNTP) { self.view.backgroundView.alpha = 1; @@ -247,7 +247,7 @@ } } -- (void)resetAfterSideSwipeSnapshot { +- (void)resetAfterSnapshot { self.view.backgroundView.alpha = 0; self.view.locationBarContainer.hidden = NO; self.view.backButton.hiddenInCurrentState = NO; @@ -331,9 +331,7 @@ return self.view.toolsMenuButton; } -- (UIColor*)backgroundColor { - if (self.view.backgroundView.hidden || self.view.backgroundView.alpha == 0) - return nil; +- (UIColor*)backgroundColorNTP { return self.view.backgroundView.backgroundColor; }
diff --git a/ios/web/download/download_task_impl.mm b/ios/web/download/download_task_impl.mm index 1d8063c..15341db 100644 --- a/ios/web/download/download_task_impl.mm +++ b/ios/web/download/download_task_impl.mm
@@ -182,6 +182,9 @@ DownloadTaskImpl::~DownloadTaskImpl() { DCHECK_CURRENTLY_ON(web::WebThread::UI); + for (auto& observer : observers_) + observer.OnDownloadDestroyed(this); + if (delegate_) { delegate_->OnTaskDestroyed(this); }
diff --git a/ios/web/download/download_task_impl_unittest.mm b/ios/web/download/download_task_impl_unittest.mm index f77b7c6..8baf503 100644 --- a/ios/web/download/download_task_impl_unittest.mm +++ b/ios/web/download/download_task_impl_unittest.mm
@@ -50,6 +50,12 @@ class MockDownloadTaskObserver : public DownloadTaskObserver { public: MOCK_METHOD1(OnDownloadUpdated, void(DownloadTask* task)); + void OnDownloadDestroyed(DownloadTask* task) override { + // Removing observer here works as a test that + // DownloadTaskObserver::OnDownloadDestroyed is actually called. + // DownloadTask DCHECKs if it is destroyed without observer removal. + task->RemoveObserver(this); + } }; // Allows waiting for DownloadTaskObserver::OnDownloadUpdated callback. @@ -128,12 +134,6 @@ task_->AddObserver(&task_observer_); } - ~DownloadTaskImplTest() { - if (task_) { - task_->RemoveObserver(&task_observer_); - } - } - // Starts the download and return NSURLSessionDataTask fake for this task. CRWFakeNSURLSessionTask* Start( std::unique_ptr<net::URLFetcherResponseWriter> writer) { @@ -674,7 +674,6 @@ ASSERT_TRUE(session_task); testing::Mock::VerifyAndClearExpectations(&task_observer_); EXPECT_CALL(task_delegate_, OnTaskDestroyed(task_.get())); - task_->RemoveObserver(&task_observer_); task_ = nullptr; // Destruct DownloadTaskImpl. EXPECT_TRUE(session_task.state = NSURLSessionTaskStateCanceling); }
diff --git a/ios/web/public/download/download_task_observer.h b/ios/web/public/download/download_task_observer.h index 42ced95..2110817 100644 --- a/ios/web/public/download/download_task_observer.h +++ b/ios/web/public/download/download_task_observer.h
@@ -23,6 +23,10 @@ // downloaded data. virtual void OnDownloadUpdated(DownloadTask* task) {} + // Called when the download task is about to be destructed. After this + // callback all references to provided DownloadTask should be cleared. + virtual void OnDownloadDestroyed(DownloadTask* task) {} + DownloadTaskObserver() = default; virtual ~DownloadTaskObserver() = default;
diff --git a/ios/web/public/test/fakes/fake_download_task.mm b/ios/web/public/test/fakes/fake_download_task.mm index a5bd772..89cf90d 100644 --- a/ios/web/public/test/fakes/fake_download_task.mm +++ b/ios/web/public/test/fakes/fake_download_task.mm
@@ -17,7 +17,10 @@ const std::string& mime_type) : original_url_(original_url), mime_type_(mime_type), identifier_(@"") {} -FakeDownloadTask::~FakeDownloadTask() = default; +FakeDownloadTask::~FakeDownloadTask() { + for (auto& observer : observers_) + observer.OnDownloadDestroyed(this); +} DownloadTask::State FakeDownloadTask::GetState() const { return state_;
diff --git a/mash/BUILD.gn b/mash/BUILD.gn index 6784a46..415a893 100644 --- a/mash/BUILD.gn +++ b/mash/BUILD.gn
@@ -14,7 +14,7 @@ deps = [ ":mash_catalog", - "//components/leveldb", + "//components/services/leveldb", "//mash/catalog_viewer", "//mash/example", "//mash/runner", @@ -41,7 +41,7 @@ testonly = true standalone_services = [ - "//components/leveldb:manifest", + "//components/services/leveldb:manifest", "//mash/catalog_viewer:manifest", "//mash/session:manifest", "//mash/task_viewer:manifest",
diff --git a/media/cdm/cdm_paths.cc b/media/cdm/cdm_paths.cc index 4c772ef..c6b00853 100644 --- a/media/cdm/cdm_paths.cc +++ b/media/cdm/cdm_paths.cc
@@ -14,20 +14,9 @@ const char kClearKeyCdmLibraryName[] = "clearkeycdm"; const char kClearKeyCdmBaseDirectory[] = "ClearKeyCdm"; - -const char kClearKeyCdmAdapterFileName[] = -#if defined(OS_MACOSX) - "clearkeycdmadapter.plugin"; -#elif defined(OS_WIN) - "clearkeycdmadapter.dll"; -#elif defined(OS_POSIX) - "libclearkeycdmadapter.so"; -#endif - const char kClearKeyCdmDisplayName[] = "Clear Key CDM"; const char kClearKeyCdmGuid[] = "C1A6B4E3-FE48-4D53-9F52-244AEEAD5335"; const char kClearKeyCdmDifferentGuid[] = "747C565D-34EE-4B0D-AC1E-4F9FB17DDB40"; -const char kClearKeyCdmPepperMimeType[] = "application/x-ppapi-clearkey-cdm"; // As the file system was initially used by the CDM running as a pepper plugin, // this ID is based on the pepper plugin MIME type.
diff --git a/media/cdm/cdm_paths.h b/media/cdm/cdm_paths.h index 0ecf0fd..83e68e61 100644 --- a/media/cdm/cdm_paths.h +++ b/media/cdm/cdm_paths.h
@@ -16,9 +16,6 @@ extern const char kClearKeyCdmBaseDirectory[]; -// Platform-specific filename relative to kClearKeyCdmBaseDirectory. -extern const char kClearKeyCdmAdapterFileName[]; - // Display name for Clear Key CDM. extern const char kClearKeyCdmDisplayName[]; @@ -29,10 +26,6 @@ // CDMs in the system. extern const char kClearKeyCdmDifferentGuid[]; -// Pepper type for Clear Key CDM. -// TODO(xhwang): Remove after switching to mojo CDM. -extern const char kClearKeyCdmPepperMimeType[]; - // Identifier used by the PluginPrivateFileSystem to identify the files stored // for the Clear Key CDM. extern const char kClearKeyCdmFileSystemId[];
diff --git a/media/cdm/library_cdm/BUILD.gn b/media/cdm/library_cdm/BUILD.gn deleted file mode 100644 index 907b168..0000000 --- a/media/cdm/library_cdm/BUILD.gn +++ /dev/null
@@ -1,30 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//chrome/process_version_rc_template.gni") -import("//media/cdm/library_cdm/cdm_paths.gni") -import("//media/cdm/library_cdm/ppapi_cdm_adapter.gni") - -process_version_rc_template("clearkeycdmadapter_resources") { - visibility = [ ":*" ] - sources = [ - "clear_key_cdm/BRANDING", - "clearkeycdmadapter.ver", - ] - output = "$target_gen_dir/clearkeycdmadapter_version.rc" -} - -ppapi_cdm_adapter("clearkeycdmadapter") { - output_dir = "$root_out_dir/$clearkey_cdm_path" - - # Check whether the plugin's origin URL is valid. - defines = [ "CHECK_DOCUMENT_URL" ] - deps = [ - ":clearkeycdmadapter_resources", - "//base", # Required for the allocator implementation. - "//media:shared_memory_support", - "//media/cdm/library_cdm/clear_key_cdm", - "//ui/gfx/geometry", - ] -}
diff --git a/media/cdm/library_cdm/clear_key_cdm/BRANDING b/media/cdm/library_cdm/clear_key_cdm/BRANDING deleted file mode 100644 index c253da9..0000000 --- a/media/cdm/library_cdm/clear_key_cdm/BRANDING +++ /dev/null
@@ -1,3 +0,0 @@ -PRODUCT_FULLNAME=External Clear Key Content Decryption Module Adapter -PRODUCT_SHORTNAME=External Clear Key -PRODUCT_DESCRIPTION=External Clear Key Content Decryption Module Adapter. Used for testing EME.
diff --git a/media/cdm/library_cdm/clearkeycdmadapter.ver b/media/cdm/library_cdm/clearkeycdmadapter.ver deleted file mode 100644 index 800abea6..0000000 --- a/media/cdm/library_cdm/clearkeycdmadapter.ver +++ /dev/null
@@ -1,2 +0,0 @@ -INTERNAL_NAME=clearkeycdmadapter_dll -ORIGINAL_FILENAME=clearkeycdmadapter.dll
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index 6a8344fc..c47a2ac6 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -16,7 +16,6 @@ "USE_VAAPI=$use_vaapi", "USE_V4L2_CODEC=$use_v4l2_codec", "USE_LIBV4L2=$use_v4lplugin", - "ENABLE_D3D11_VIDEO_DECODER=$enable_d3d11_video_decoder", ] } @@ -249,6 +248,14 @@ if (is_win) { sources += [ + "windows/d3d11_h264_accelerator.cc", + "windows/d3d11_h264_accelerator.h", + "windows/d3d11_picture_buffer.cc", + "windows/d3d11_picture_buffer.h", + "windows/d3d11_video_decoder.cc", + "windows/d3d11_video_decoder.h", + "windows/d3d11_video_decoder_impl.cc", + "windows/d3d11_video_decoder_impl.h", "windows/dxva_picture_buffer_win.cc", "windows/dxva_picture_buffer_win.h", "windows/dxva_video_decode_accelerator_win.cc", @@ -284,18 +291,6 @@ "/DELAYLOAD:mf.dll", "/DELAYLOAD:mfplat.dll", ] - if (enable_d3d11_video_decoder) { - sources += [ - "windows/d3d11_h264_accelerator.cc", - "windows/d3d11_h264_accelerator.h", - "windows/d3d11_picture_buffer.cc", - "windows/d3d11_picture_buffer.h", - "windows/d3d11_video_decoder.cc", - "windows/d3d11_video_decoder.h", - "windows/d3d11_video_decoder_impl.cc", - "windows/d3d11_video_decoder_impl.h", - ] - } if (enable_library_cdms) { sources += [ "windows/d3d11_cdm_proxy.cc",
diff --git a/media/gpu/vaapi/BUILD.gn b/media/gpu/vaapi/BUILD.gn index 27185f1..e4bc702 100644 --- a/media/gpu/vaapi/BUILD.gn +++ b/media/gpu/vaapi/BUILD.gn
@@ -5,6 +5,8 @@ import("//build/config/features.gni") import("//build/config/ui.gni") import("//media/gpu/args.gni") +import("//ui/gl/features.gni") +import("//ui/ozone/ozone.gni") assert(use_vaapi) @@ -51,35 +53,36 @@ source_set("vaapi") { defines = [ "MEDIA_GPU_IMPLEMENTATION" ] sources = [ - "va_surface.cc", - "va_surface.h", - "vaapi_decode_surface.cc", - "vaapi_decode_surface.h", - "vaapi_jpeg_decode_accelerator.cc", - "vaapi_jpeg_decode_accelerator.h", - "vaapi_jpeg_decoder.cc", - "vaapi_jpeg_decoder.h", - "vaapi_jpeg_encode_accelerator.cc", - "vaapi_jpeg_encode_accelerator.h", - "vaapi_jpeg_encoder.cc", - "vaapi_jpeg_encoder.h", - "vaapi_picture.cc", - "vaapi_picture.h", - "vaapi_picture_factory.cc", - "vaapi_picture_factory.h", - "vaapi_video_decode_accelerator.cc", - "vaapi_video_decode_accelerator.h", - "vaapi_video_encode_accelerator.cc", - "vaapi_video_encode_accelerator.h", - "vaapi_h264_accelerator.cc", - "vaapi_h264_accelerator.h", - "vaapi_vp8_accelerator.cc", - "vaapi_vp8_accelerator.h", - "vaapi_vp9_accelerator.cc", - "vaapi_vp9_accelerator.h", - "vaapi_wrapper.cc", - "vaapi_wrapper.h", - ] + get_target_outputs(":libva_generate_stubs") + "va_surface.cc", + "va_surface.h", + "vaapi_decode_surface.cc", + "vaapi_decode_surface.h", + "vaapi_h264_accelerator.cc", + "vaapi_h264_accelerator.h", + "vaapi_jpeg_decode_accelerator.cc", + "vaapi_jpeg_decode_accelerator.h", + "vaapi_jpeg_decoder.cc", + "vaapi_jpeg_decoder.h", + "vaapi_jpeg_encode_accelerator.cc", + "vaapi_jpeg_encode_accelerator.h", + "vaapi_jpeg_encoder.cc", + "vaapi_jpeg_encoder.h", + "vaapi_picture.cc", + "vaapi_picture.h", + "vaapi_picture_factory.cc", + "vaapi_picture_factory.h", + "vaapi_video_decode_accelerator.cc", + "vaapi_video_decode_accelerator.h", + "vaapi_video_encode_accelerator.cc", + "vaapi_video_encode_accelerator.h", + "vaapi_vp8_accelerator.cc", + "vaapi_vp8_accelerator.h", + "vaapi_vp9_accelerator.cc", + "vaapi_vp9_accelerator.h", + "vaapi_wrapper.cc", + "vaapi_wrapper.h", + ] + sources += get_target_outputs(":libva_generate_stubs") configs += [ "//third_party/libyuv:libyuv_config" ] @@ -90,24 +93,34 @@ "//media/gpu:common", "//third_party/libyuv", ] + if (use_x11) { configs += [ "//build/config/linux:x11" ] deps += [ "//ui/gfx/x" ] sources += [ - "vaapi_tfp_picture.cc", - "vaapi_tfp_picture.h", + "vaapi_picture_tfp.cc", + "vaapi_picture_tfp.h", ] } - if (is_linux) { + if (ozone_platform_gbm || use_egl) { sources += [ - "vaapi_drm_picture.cc", - "vaapi_drm_picture.h", + "vaapi_picture_native_pixmap.cc", + "vaapi_picture_native_pixmap.h", ] - } - - if (use_ozone) { - deps += [ "//ui/ozone" ] + if (ozone_platform_gbm) { + sources += [ + "vaapi_picture_native_pixmap_ozone.cc", + "vaapi_picture_native_pixmap_ozone.h", + ] + deps += [ "//ui/ozone" ] + } + if (use_egl) { + sources += [ + "vaapi_picture_native_pixmap_egl.cc", + "vaapi_picture_native_pixmap_egl.h", + ] + } } }
diff --git a/media/gpu/vaapi/vaapi_drm_picture.cc b/media/gpu/vaapi/vaapi_drm_picture.cc deleted file mode 100644 index 7bf98222..0000000 --- a/media/gpu/vaapi/vaapi_drm_picture.cc +++ /dev/null
@@ -1,219 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/gpu/vaapi/vaapi_drm_picture.h" - -#include "base/file_descriptor_posix.h" -#include "media/gpu/vaapi/va_surface.h" -#include "media/gpu/vaapi/vaapi_wrapper.h" -#include "ui/gfx/gpu_memory_buffer.h" -#include "ui/gfx/linux/native_pixmap_dmabuf.h" -#include "ui/gfx/native_pixmap.h" -#include "ui/gl/gl_bindings.h" -#include "ui/gl/gl_image_native_pixmap.h" -#include "ui/gl/scoped_binders.h" - -#if defined(USE_OZONE) -#include "ui/ozone/public/ozone_platform.h" -#include "ui/ozone/public/surface_factory_ozone.h" -#endif - -namespace media { - -namespace { - -static unsigned BufferFormatToInternalFormat(gfx::BufferFormat format) { - switch (format) { - case gfx::BufferFormat::BGRX_8888: - case gfx::BufferFormat::RGBX_8888: - return GL_RGB; - - case gfx::BufferFormat::BGRA_8888: - return GL_BGRA_EXT; - - case gfx::BufferFormat::YVU_420: - return GL_RGB_YCRCB_420_CHROMIUM; - - default: - NOTREACHED(); - return GL_BGRA_EXT; - } -} - -} // anonymous namespace - -VaapiDrmPicture::VaapiDrmPicture( - const scoped_refptr<VaapiWrapper>& vaapi_wrapper, - const MakeGLContextCurrentCallback& make_context_current_cb, - const BindGLImageCallback& bind_image_cb, - int32_t picture_buffer_id, - const gfx::Size& size, - uint32_t texture_id, - uint32_t client_texture_id, - uint32_t texture_target) - : VaapiPicture(vaapi_wrapper, - make_context_current_cb, - bind_image_cb, - picture_buffer_id, - size, - texture_id, - client_texture_id, - texture_target) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -} - -VaapiDrmPicture::~VaapiDrmPicture() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (gl_image_ && make_context_current_cb_.Run()) { - gl_image_->ReleaseTexImage(texture_target_); - DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR)); - } -} - -bool VaapiDrmPicture::Initialize() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(pixmap_); - - // Create a |va_surface_| from dmabuf fds (pixmap->GetDmaBufFd) - va_surface_ = vaapi_wrapper_->CreateVASurfaceForPixmap(pixmap_); - if (!va_surface_) { - LOG(ERROR) << "Failed creating VASurface for NativePixmap"; - return false; - } - -#if defined(USE_OZONE) - // Import dmabuf fds into the output gl texture through EGLImage. - if (texture_id_ != 0 && !make_context_current_cb_.is_null()) { - if (!make_context_current_cb_.Run()) - return false; - - gl::ScopedTextureBinder texture_binder(texture_target_, texture_id_); - - gfx::BufferFormat format = pixmap_->GetBufferFormat(); - - scoped_refptr<gl::GLImageNativePixmap> image(new gl::GLImageNativePixmap( - size_, BufferFormatToInternalFormat(format))); - if (!image->Initialize(pixmap_.get(), format)) { - LOG(ERROR) << "Failed to create GLImage"; - return false; - } - gl_image_ = image; - if (!gl_image_->BindTexImage(texture_target_)) { - LOG(ERROR) << "Failed to bind texture to GLImage"; - return false; - } - } -#else - // On non-ozone, no need to import dmabuf fds into output the gl texture - // because the dmabuf fds have been made from it. - DCHECK(pixmap_->AreDmaBufFdsValid()); -#endif - - if (client_texture_id_ != 0 && !bind_image_cb_.is_null()) { - if (!bind_image_cb_.Run(client_texture_id_, texture_target_, gl_image_, - true)) { - LOG(ERROR) << "Failed to bind client_texture_id"; - return false; - } - } - - return true; -} - -bool VaapiDrmPicture::Allocate(gfx::BufferFormat format) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - -// The goal of this method (ozone and non-ozone) is to allocate the -// |pixmap_| which is a gl::GLImageNativePixmap. -#if defined(USE_OZONE) - ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); - ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); - pixmap_ = factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size_, - format, gfx::BufferUsage::SCANOUT); -#else - // Export the gl texture as dmabuf. - if (texture_id_ != 0 && !make_context_current_cb_.is_null()) { - if (!make_context_current_cb_.Run()) - return false; - - scoped_refptr<gl::GLImageNativePixmap> image(new gl::GLImageNativePixmap( - size_, BufferFormatToInternalFormat(format))); - - // Create an EGLImage from a gl texture - if (!image->InitializeFromTexture(texture_id_)) { - DLOG(ERROR) << "Failed to initialize eglimage from texture id: " - << texture_id_; - return false; - } - - // Export the EGLImage as dmabuf. - gfx::NativePixmapHandle native_pixmap_handle = image->ExportHandle(); - if (!native_pixmap_handle.planes.size()) { - DLOG(ERROR) << "Failed to export EGLImage as dmabuf fds"; - return false; - } - - // Convert NativePixmapHandle to NativePixmapDmaBuf. - scoped_refptr<gfx::NativePixmap> native_pixmap_dmabuf( - new gfx::NativePixmapDmaBuf(size_, format, native_pixmap_handle)); - if (!native_pixmap_dmabuf->AreDmaBufFdsValid()) { - DLOG(ERROR) << "Invalid dmabuf fds"; - return false; - } - - if (!image->BindTexImage(texture_target_)) { - DLOG(ERROR) << "Failed to bind texture to GLImage"; - return false; - } - - // The |pixmap_| takes ownership of the dmabuf fds. So the only reason to - // to keep a reference on the image is because the GPU service needs to - // track this image as it will be attached to a client texture. - pixmap_ = native_pixmap_dmabuf; - gl_image_ = image; - } -#endif // USE_OZONE - - if (!pixmap_) { - DVLOG(1) << "Failed allocating a pixmap"; - return false; - } - - return Initialize(); -} - -bool VaapiDrmPicture::ImportGpuMemoryBufferHandle( - gfx::BufferFormat format, - const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -#if defined(USE_OZONE) - ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); - ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); - // CreateNativePixmapFromHandle() will take ownership of the handle. - pixmap_ = factory->CreateNativePixmapFromHandle( - gfx::kNullAcceleratedWidget, size_, format, - gpu_memory_buffer_handle.native_pixmap_handle); -#else - NOTIMPLEMENTED(); -#endif - if (!pixmap_) { - DVLOG(1) << "Failed creating a pixmap from a native handle"; - return false; - } - - return Initialize(); -} - -bool VaapiDrmPicture::DownloadFromSurface( - const scoped_refptr<VASurface>& va_surface) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return vaapi_wrapper_->BlitSurface(va_surface, va_surface_); -} - -bool VaapiDrmPicture::AllowOverlay() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return true; -} - -} // namespace media
diff --git a/media/gpu/vaapi/vaapi_drm_picture.h b/media/gpu/vaapi/vaapi_drm_picture.h deleted file mode 100644 index d6acda3..0000000 --- a/media/gpu/vaapi/vaapi_drm_picture.h +++ /dev/null
@@ -1,73 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This file contains an implementation of picture allocation for the -// Ozone window system used by VaapiVideoDecodeAccelerator to produce -// output pictures. - -#ifndef MEDIA_GPU_VAAPI_VAAPI_DRM_PICTURE_H_ -#define MEDIA_GPU_VAAPI_VAAPI_DRM_PICTURE_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "media/gpu/vaapi/vaapi_picture.h" -#include "ui/gfx/buffer_types.h" -#include "ui/gfx/geometry/size.h" - -namespace gl { -class GLImage; -} - -namespace gfx { -class NativePixmap; -} - -namespace media { - -class VaapiWrapper; - -// Implementation of VaapiPicture for the ozone/drm backed chromium. -class VaapiDrmPicture : public VaapiPicture { - public: - VaapiDrmPicture(const scoped_refptr<VaapiWrapper>& vaapi_wrapper, - const MakeGLContextCurrentCallback& make_context_current_cb, - const BindGLImageCallback& bind_image_cb_, - int32_t picture_buffer_id, - const gfx::Size& size, - uint32_t texture_id, - uint32_t client_texture_id, - uint32_t texture_target); - - ~VaapiDrmPicture() override; - - bool Allocate(gfx::BufferFormat format) override; - bool ImportGpuMemoryBufferHandle( - gfx::BufferFormat format, - const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) override; - - bool DownloadFromSurface(const scoped_refptr<VASurface>& va_surface) override; - - bool AllowOverlay() const override; - - private: - bool Initialize(); - - // Ozone buffer, the storage of the EGLImage and the VASurface. - scoped_refptr<gfx::NativePixmap> pixmap_; - - // EGLImage bound to the GL textures used by the VDA client. - scoped_refptr<gl::GLImage> gl_image_; - - // VASurface used to transfer from the decoder's pixel format. - scoped_refptr<VASurface> va_surface_; - - DISALLOW_COPY_AND_ASSIGN(VaapiDrmPicture); -}; - -} // namespace media - -#endif // MEDIA_GPU_VAAPI_VAAPI_DRM_PICTURE_H_
diff --git a/media/gpu/vaapi/vaapi_picture_factory.cc b/media/gpu/vaapi/vaapi_picture_factory.cc index 5f4aa40..20ae5ab 100644 --- a/media/gpu/vaapi/vaapi_picture_factory.cc +++ b/media/gpu/vaapi/vaapi_picture_factory.cc
@@ -7,10 +7,14 @@ #include "media/gpu/vaapi/vaapi_wrapper.h" #include "ui/gl/gl_bindings.h" -#include "media/gpu/vaapi/vaapi_drm_picture.h" - #if defined(USE_X11) -#include "media/gpu/vaapi/vaapi_tfp_picture.h" +#include "media/gpu/vaapi/vaapi_picture_tfp.h" +#endif +#if defined(USE_OZONE) +#include "media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h" +#endif +#if defined(USE_EGL) +#include "media/gpu/vaapi/vaapi_picture_native_pixmap_egl.h" #endif namespace media { @@ -51,10 +55,17 @@ // Select DRM(egl) / TFP(glx) at runtime with --use-gl=egl / --use-gl=desktop switch (GetVaapiImplementation(gl::GetGLImplementation())) { case kVaapiImplementationDrm: - picture.reset(new VaapiDrmPicture(vaapi_wrapper, make_context_current_cb, - bind_image_cb, picture_buffer_id, size, - texture_id, client_texture_id, - texture_target)); +#if defined(USE_OZONE) + picture.reset(new VaapiPictureNativePixmapOzone( + vaapi_wrapper, make_context_current_cb, bind_image_cb, + picture_buffer_id, size, texture_id, client_texture_id, + texture_target)); +#elif defined(USE_EGL) + picture.reset(new VaapiPictureNativePixmapEgl( + vaapi_wrapper, make_context_current_cb, bind_image_cb, + picture_buffer_id, size, texture_id, client_texture_id, + texture_target)); +#endif break; #if defined(USE_X11)
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap.cc b/media/gpu/vaapi/vaapi_picture_native_pixmap.cc new file mode 100644 index 0000000..6ef8b6e --- /dev/null +++ b/media/gpu/vaapi/vaapi_picture_native_pixmap.cc
@@ -0,0 +1,67 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/gpu/vaapi/vaapi_picture_native_pixmap.h" + +#include "media/gpu/vaapi/va_surface.h" +#include "media/gpu/vaapi/vaapi_wrapper.h" +#include "ui/gfx/buffer_format_util.h" +#include "ui/gfx/gpu_memory_buffer.h" +#include "ui/gfx/linux/native_pixmap_dmabuf.h" +#include "ui/gfx/native_pixmap.h" +#include "ui/gl/gl_image_native_pixmap.h" + +namespace media { + +VaapiPictureNativePixmap::VaapiPictureNativePixmap( + const scoped_refptr<VaapiWrapper>& vaapi_wrapper, + const MakeGLContextCurrentCallback& make_context_current_cb, + const BindGLImageCallback& bind_image_cb, + int32_t picture_buffer_id, + const gfx::Size& size, + uint32_t texture_id, + uint32_t client_texture_id, + uint32_t texture_target) + : VaapiPicture(vaapi_wrapper, + make_context_current_cb, + bind_image_cb, + picture_buffer_id, + size, + texture_id, + client_texture_id, + texture_target) {} + +VaapiPictureNativePixmap::~VaapiPictureNativePixmap() = default; + +bool VaapiPictureNativePixmap::DownloadFromSurface( + const scoped_refptr<VASurface>& va_surface) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return vaapi_wrapper_->BlitSurface(va_surface, va_surface_); +} + +bool VaapiPictureNativePixmap::AllowOverlay() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return true; +} + +unsigned VaapiPictureNativePixmap::BufferFormatToInternalFormat( + gfx::BufferFormat format) const { + switch (format) { + case gfx::BufferFormat::BGRX_8888: + case gfx::BufferFormat::RGBX_8888: + return GL_RGB; + + case gfx::BufferFormat::BGRA_8888: + return GL_BGRA_EXT; + + case gfx::BufferFormat::YVU_420: + return GL_RGB_YCRCB_420_CHROMIUM; + + default: + NOTREACHED() << gfx::BufferFormatToString(format); + return GL_BGRA_EXT; + } +} + +} // namespace media
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap.h b/media/gpu/vaapi/vaapi_picture_native_pixmap.h new file mode 100644 index 0000000..ab852425 --- /dev/null +++ b/media/gpu/vaapi/vaapi_picture_native_pixmap.h
@@ -0,0 +1,63 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_H_ +#define MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_H_ + +#include <stdint.h> + +#include "base/memory/ref_counted.h" +#include "media/gpu/vaapi/vaapi_picture.h" +#include "ui/gfx/buffer_types.h" +#include "ui/gfx/geometry/size.h" + +namespace gl { +class GLImage; +} + +namespace gfx { +class NativePixmap; +} + +namespace media { + +class VaapiWrapper; + +// Implementation of VaapiPicture based on NativePixmaps. +class VaapiPictureNativePixmap : public VaapiPicture { + public: + VaapiPictureNativePixmap( + const scoped_refptr<VaapiWrapper>& vaapi_wrapper, + const MakeGLContextCurrentCallback& make_context_current_cb, + const BindGLImageCallback& bind_image_cb_, + int32_t picture_buffer_id, + const gfx::Size& size, + uint32_t texture_id, + uint32_t client_texture_id, + uint32_t texture_target); + ~VaapiPictureNativePixmap() override; + + // VaapiPicture implementation. + bool DownloadFromSurface(const scoped_refptr<VASurface>& va_surface) override; + bool AllowOverlay() const override; + + unsigned BufferFormatToInternalFormat(gfx::BufferFormat format) const; + + protected: + // Ozone buffer, the storage of the EGLImage and the VASurface. + scoped_refptr<gfx::NativePixmap> pixmap_; + + // GLImage bound to the GL textures used by the VDA client. + scoped_refptr<gl::GLImage> gl_image_; + + // VASurface used to transfer from the decoder's pixel format. + scoped_refptr<VASurface> va_surface_; + + private: + DISALLOW_COPY_AND_ASSIGN(VaapiPictureNativePixmap); +}; + +} // namespace media + +#endif // MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_H_
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc b/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc new file mode 100644 index 0000000..f7d4981 --- /dev/null +++ b/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.cc
@@ -0,0 +1,133 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/gpu/vaapi/vaapi_picture_native_pixmap_egl.h" + +#include "base/file_descriptor_posix.h" +#include "media/gpu/vaapi/va_surface.h" +#include "media/gpu/vaapi/vaapi_wrapper.h" +#include "ui/gfx/linux/native_pixmap_dmabuf.h" +#include "ui/gfx/native_pixmap.h" +#include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_image_native_pixmap.h" +#include "ui/gl/scoped_binders.h" + +namespace media { + +VaapiPictureNativePixmapEgl::VaapiPictureNativePixmapEgl( + const scoped_refptr<VaapiWrapper>& vaapi_wrapper, + const MakeGLContextCurrentCallback& make_context_current_cb, + const BindGLImageCallback& bind_image_cb, + int32_t picture_buffer_id, + const gfx::Size& size, + uint32_t texture_id, + uint32_t client_texture_id, + uint32_t texture_target) + : VaapiPictureNativePixmap(vaapi_wrapper, + make_context_current_cb, + bind_image_cb, + picture_buffer_id, + size, + texture_id, + client_texture_id, + texture_target) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +VaapiPictureNativePixmapEgl::~VaapiPictureNativePixmapEgl() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (gl_image_ && make_context_current_cb_.Run()) { + gl_image_->ReleaseTexImage(texture_target_); + DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR)); + } +} + +bool VaapiPictureNativePixmapEgl::Initialize() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(pixmap_); + + // Create a |va_surface_| from dmabuf fds (pixmap->GetDmaBufFd) + va_surface_ = vaapi_wrapper_->CreateVASurfaceForPixmap(pixmap_); + if (!va_surface_) { + LOG(ERROR) << "Failed creating VASurface for NativePixmap"; + return false; + } + + // On non-ozone, no need to import dmabuf fds into output the gl texture + // because the dmabuf fds have been made from it. + DCHECK(pixmap_->AreDmaBufFdsValid()); + + if (client_texture_id_ != 0 && !bind_image_cb_.is_null()) { + if (!bind_image_cb_.Run(client_texture_id_, texture_target_, gl_image_, + true)) { + LOG(ERROR) << "Failed to bind client_texture_id"; + return false; + } + } + + return true; +} + +bool VaapiPictureNativePixmapEgl::Allocate(gfx::BufferFormat format) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // Export the gl texture as dmabuf. + if (texture_id_ != 0 && !make_context_current_cb_.is_null()) { + if (!make_context_current_cb_.Run()) + return false; + + scoped_refptr<gl::GLImageNativePixmap> image(new gl::GLImageNativePixmap( + size_, BufferFormatToInternalFormat(format))); + + // Create an EGLImage from a gl texture + if (!image->InitializeFromTexture(texture_id_)) { + DLOG(ERROR) << "Failed to initialize eglimage from texture id: " + << texture_id_; + return false; + } + + // Export the EGLImage as dmabuf. + gfx::NativePixmapHandle native_pixmap_handle = image->ExportHandle(); + if (!native_pixmap_handle.planes.size()) { + DLOG(ERROR) << "Failed to export EGLImage as dmabuf fds"; + return false; + } + + // Convert NativePixmapHandle to NativePixmapDmaBuf. + scoped_refptr<gfx::NativePixmap> native_pixmap_dmabuf( + new gfx::NativePixmapDmaBuf(size_, format, native_pixmap_handle)); + if (!native_pixmap_dmabuf->AreDmaBufFdsValid()) { + DLOG(ERROR) << "Invalid dmabuf fds"; + return false; + } + + if (!image->BindTexImage(texture_target_)) { + DLOG(ERROR) << "Failed to bind texture to GLImage"; + return false; + } + + // The |pixmap_| takes ownership of the dmabuf fds. So the only reason + // to keep a reference on the image is because the GPU service needs to + // track this image as it will be attached to a client texture. + pixmap_ = native_pixmap_dmabuf; + gl_image_ = image; + } + + if (!pixmap_) { + DVLOG(1) << "Failed allocating a pixmap"; + return false; + } + + return Initialize(); +} + +bool VaapiPictureNativePixmapEgl::ImportGpuMemoryBufferHandle( + gfx::BufferFormat format, + const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); + return false; +} + +} // namespace media
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.h b/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.h new file mode 100644 index 0000000..17e17e4 --- /dev/null +++ b/media/gpu/vaapi/vaapi_picture_native_pixmap_egl.h
@@ -0,0 +1,51 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_EGL_H_ +#define MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_EGL_H_ + +#include <stdint.h> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "media/gpu/vaapi/vaapi_picture_native_pixmap.h" +#include "ui/gfx/buffer_types.h" +#include "ui/gfx/geometry/size.h" + +namespace media { + +class VaapiWrapper; + +// Implementation of VaapiPictureNativePixmap for EGL backends, see +// https://crbug.com/785201. +class VaapiPictureNativePixmapEgl : public VaapiPictureNativePixmap { + public: + VaapiPictureNativePixmapEgl( + const scoped_refptr<VaapiWrapper>& vaapi_wrapper, + const MakeGLContextCurrentCallback& make_context_current_cb, + const BindGLImageCallback& bind_image_cb_, + int32_t picture_buffer_id, + const gfx::Size& size, + uint32_t texture_id, + uint32_t client_texture_id, + uint32_t texture_target); + + ~VaapiPictureNativePixmapEgl() override; + + // VaapiPicture implementation. + bool Allocate(gfx::BufferFormat format) override; + bool ImportGpuMemoryBufferHandle( + gfx::BufferFormat format, + const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) override; + + private: + bool Initialize(); + + DISALLOW_COPY_AND_ASSIGN(VaapiPictureNativePixmapEgl); +}; + +} // namespace media + +#endif // MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_EGL_H_
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc b/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc new file mode 100644 index 0000000..48e4850c --- /dev/null +++ b/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.cc
@@ -0,0 +1,128 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h" + +#include "media/gpu/vaapi/va_surface.h" +#include "media/gpu/vaapi/vaapi_wrapper.h" +#include "ui/gfx/gpu_memory_buffer.h" +#include "ui/gfx/linux/native_pixmap_dmabuf.h" +#include "ui/gfx/native_pixmap.h" +#include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_image_native_pixmap.h" +#include "ui/gl/scoped_binders.h" +#include "ui/ozone/public/ozone_platform.h" +#include "ui/ozone/public/surface_factory_ozone.h" + +namespace media { + +VaapiPictureNativePixmapOzone::VaapiPictureNativePixmapOzone( + const scoped_refptr<VaapiWrapper>& vaapi_wrapper, + const MakeGLContextCurrentCallback& make_context_current_cb, + const BindGLImageCallback& bind_image_cb, + int32_t picture_buffer_id, + const gfx::Size& size, + uint32_t texture_id, + uint32_t client_texture_id, + uint32_t texture_target) + : VaapiPictureNativePixmap(vaapi_wrapper, + make_context_current_cb, + bind_image_cb, + picture_buffer_id, + size, + texture_id, + client_texture_id, + texture_target) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +VaapiPictureNativePixmapOzone::~VaapiPictureNativePixmapOzone() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (gl_image_ && make_context_current_cb_.Run()) { + gl_image_->ReleaseTexImage(texture_target_); + DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR)); + } +} + +bool VaapiPictureNativePixmapOzone::Initialize() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(pixmap_); + + // Create a |va_surface_| from dmabuf fds (pixmap->GetDmaBufFd) + va_surface_ = vaapi_wrapper_->CreateVASurfaceForPixmap(pixmap_); + if (!va_surface_) { + LOG(ERROR) << "Failed creating VASurface for NativePixmap"; + return false; + } + + // Import dmabuf fds into the output gl texture through EGLImage. + if (texture_id_ != 0 && !make_context_current_cb_.is_null()) { + if (!make_context_current_cb_.Run()) + return false; + + gl::ScopedTextureBinder texture_binder(texture_target_, texture_id_); + + gfx::BufferFormat format = pixmap_->GetBufferFormat(); + + scoped_refptr<gl::GLImageNativePixmap> image(new gl::GLImageNativePixmap( + size_, BufferFormatToInternalFormat(format))); + if (!image->Initialize(pixmap_.get(), format)) { + LOG(ERROR) << "Failed to create GLImage"; + return false; + } + gl_image_ = image; + if (!gl_image_->BindTexImage(texture_target_)) { + LOG(ERROR) << "Failed to bind texture to GLImage"; + return false; + } + } + + if (client_texture_id_ != 0 && !bind_image_cb_.is_null()) { + if (!bind_image_cb_.Run(client_texture_id_, texture_target_, gl_image_, + true)) { + LOG(ERROR) << "Failed to bind client_texture_id"; + return false; + } + } + + return true; +} + +bool VaapiPictureNativePixmapOzone::Allocate(gfx::BufferFormat format) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); + ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); + pixmap_ = factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size_, + format, gfx::BufferUsage::SCANOUT); + + if (!pixmap_) { + DVLOG(1) << "Failed allocating a pixmap"; + return false; + } + + return Initialize(); +} + +bool VaapiPictureNativePixmapOzone::ImportGpuMemoryBufferHandle( + gfx::BufferFormat format, + const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); + ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); + // CreateNativePixmapFromHandle() will take ownership of the handle. + pixmap_ = factory->CreateNativePixmapFromHandle( + gfx::kNullAcceleratedWidget, size_, format, + gpu_memory_buffer_handle.native_pixmap_handle); + + if (!pixmap_) { + DVLOG(1) << "Failed creating a pixmap from a native handle"; + return false; + } + + return Initialize(); +} + +} // namespace media
diff --git a/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h b/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h new file mode 100644 index 0000000..23ebfe0a --- /dev/null +++ b/media/gpu/vaapi/vaapi_picture_native_pixmap_ozone.h
@@ -0,0 +1,50 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_OZONE_H_ +#define MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_OZONE_H_ + +#include <stdint.h> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "media/gpu/vaapi/vaapi_picture_native_pixmap.h" +#include "ui/gfx/buffer_types.h" +#include "ui/gfx/geometry/size.h" + +namespace media { + +class VaapiWrapper; + +// Implementation of VaapiPictureNativePixmap using Ozone. +class VaapiPictureNativePixmapOzone : public VaapiPictureNativePixmap { + public: + VaapiPictureNativePixmapOzone( + const scoped_refptr<VaapiWrapper>& vaapi_wrapper, + const MakeGLContextCurrentCallback& make_context_current_cb, + const BindGLImageCallback& bind_image_cb_, + int32_t picture_buffer_id, + const gfx::Size& size, + uint32_t texture_id, + uint32_t client_texture_id, + uint32_t texture_target); + + ~VaapiPictureNativePixmapOzone() override; + + // VaapiPicture implementation. + bool Allocate(gfx::BufferFormat format) override; + bool ImportGpuMemoryBufferHandle( + gfx::BufferFormat format, + const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) override; + + private: + bool Initialize(); + + DISALLOW_COPY_AND_ASSIGN(VaapiPictureNativePixmapOzone); +}; + +} // namespace media + +#endif // MEDIA_GPU_VAAPI_VAAPI_PICTURE_NATIVE_PIXMAP_OZONE_H_
diff --git a/media/gpu/vaapi/vaapi_tfp_picture.cc b/media/gpu/vaapi/vaapi_picture_tfp.cc similarity index 98% rename from media/gpu/vaapi/vaapi_tfp_picture.cc rename to media/gpu/vaapi/vaapi_picture_tfp.cc index 4e45b57..30d6f0d97 100644 --- a/media/gpu/vaapi/vaapi_tfp_picture.cc +++ b/media/gpu/vaapi/vaapi_picture_tfp.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "media/gpu/vaapi/vaapi_tfp_picture.h" +#include "media/gpu/vaapi/vaapi_picture_tfp.h" #include "media/gpu/vaapi/va_surface.h" #include "media/gpu/vaapi/vaapi_wrapper.h"
diff --git a/media/gpu/vaapi/vaapi_tfp_picture.h b/media/gpu/vaapi/vaapi_picture_tfp.h similarity index 79% rename from media/gpu/vaapi/vaapi_tfp_picture.h rename to media/gpu/vaapi/vaapi_picture_tfp.h index a386118..a9ba8a1 100644 --- a/media/gpu/vaapi/vaapi_tfp_picture.h +++ b/media/gpu/vaapi/vaapi_picture_tfp.h
@@ -1,13 +1,9 @@ // Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// -// This file contains an implementation of picture allocation for the -// X11 window system used by VaapiVideoDecodeAccelerator to produce -// output pictures. -#ifndef MEDIA_GPU_VAAPI_VAAPI_TFP_PICTURE_H_ -#define MEDIA_GPU_VAAPI_VAAPI_TFP_PICTURE_H_ +#ifndef MEDIA_GPU_VAAPI_VAAPI_PICTURE_TFP_H_ +#define MEDIA_GPU_VAAPI_VAAPI_PICTURE_TFP_H_ #include <stdint.h> @@ -25,7 +21,8 @@ class VaapiWrapper; -// Implementation of VaapiPicture for the X11 backed chromium. +// Implementation of VaapiPicture for the X11 backends with Texture-From-Pixmap +// extension. class VaapiTFPPicture : public VaapiPicture { public: VaapiTFPPicture(const scoped_refptr<VaapiWrapper>& vaapi_wrapper, @@ -39,11 +36,11 @@ ~VaapiTFPPicture() override; + // VaapiPicture implementation. bool Allocate(gfx::BufferFormat format) override; bool ImportGpuMemoryBufferHandle( gfx::BufferFormat format, const gfx::GpuMemoryBufferHandle& gpu_memory_buffer_handle) override; - bool DownloadFromSurface(const scoped_refptr<VASurface>& va_surface) override; private: @@ -59,4 +56,4 @@ } // namespace media -#endif // MEDIA_GPU_VAAPI_VAAPI_TFP_PICTURE_H_ +#endif // MEDIA_GPU_VAAPI_VAAPI_PICTURE_TFP_H_
diff --git a/media/gpu/windows/d3d11_picture_buffer.cc b/media/gpu/windows/d3d11_picture_buffer.cc index 022c60d..1fbb749 100644 --- a/media/gpu/windows/d3d11_picture_buffer.cc +++ b/media/gpu/windows/d3d11_picture_buffer.cc
@@ -28,7 +28,7 @@ namespace { static bool MakeContextCurrent(gpu::CommandBufferStub* stub) { - return stub && stub->decoder()->MakeCurrent(); + return stub && stub->decoder_context()->MakeCurrent(); } } // namespace @@ -100,8 +100,8 @@ // TODO(liberato): see GpuVideoFrameFactory. // stub_->AddDestructionObserver(this); - auto decoder_helper = GLES2DecoderHelper::Create(stub->decoder()); - gpu::gles2::ContextGroup* group = stub->decoder()->GetContextGroup(); + auto decoder_helper = GLES2DecoderHelper::Create(stub->decoder_context()); + gpu::gles2::ContextGroup* group = stub->decoder_context()->GetContextGroup(); gpu::MailboxManager* mailbox_manager = group->mailbox_manager(); gpu::gles2::TextureManager* texture_manager = group->texture_manager(); RETURN_ON_FAILURE(!!texture_manager, "No texture manager", false);
diff --git a/media/gpu/windows/d3d11_video_decoder.cc b/media/gpu/windows/d3d11_video_decoder.cc index 7440598..1489c65 100644 --- a/media/gpu/windows/d3d11_video_decoder.cc +++ b/media/gpu/windows/d3d11_video_decoder.cc
@@ -73,8 +73,8 @@ bool low_delay, CdmContext* cdm_context, const InitCB& init_cb, - const OutputCB& output_cb const - WaitingForDecryptionKeyCB& /* waiting_for_decryption_key_cb */) { + const OutputCB& output_cb, + const WaitingForDecryptionKeyCB& waiting_for_decryption_key_cb) { bool is_h264 = config.profile() >= H264PROFILE_MIN && config.profile() <= H264PROFILE_MAX; if (!is_h264) { @@ -90,7 +90,9 @@ base::BindOnce( &VideoDecoder::Initialize, impl_weak_, config, low_delay, cdm_context, BindToCurrentThreadIfWeakPtr(weak_factory_.GetWeakPtr(), init_cb), - BindToCurrentThreadIfWeakPtr(weak_factory_.GetWeakPtr(), output_cb))); + BindToCurrentThreadIfWeakPtr(weak_factory_.GetWeakPtr(), output_cb), + BindToCurrentThreadIfWeakPtr(weak_factory_.GetWeakPtr(), + waiting_for_decryption_key_cb))); } void D3D11VideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
diff --git a/media/gpu/windows/d3d11_video_decoder_impl.cc b/media/gpu/windows/d3d11_video_decoder_impl.cc index 0e9c469..a56fc02 100644 --- a/media/gpu/windows/d3d11_video_decoder_impl.cc +++ b/media/gpu/windows/d3d11_video_decoder_impl.cc
@@ -22,7 +22,7 @@ namespace { static bool MakeContextCurrent(gpu::CommandBufferStub* stub) { - return stub && stub->decoder()->MakeCurrent(); + return stub && stub->decoder_context()->MakeCurrent(); } } // namespace @@ -41,11 +41,13 @@ return "D3D11VideoDecoderImpl"; } -void D3D11VideoDecoderImpl::Initialize(const VideoDecoderConfig& config, - bool low_delay, - CdmContext* cdm_context, - const InitCB& init_cb, - const OutputCB& output_cb) { +void D3D11VideoDecoderImpl::Initialize( + const VideoDecoderConfig& config, + bool low_delay, + CdmContext* cdm_context, + const InitCB& init_cb, + const OutputCB& output_cb, + const WaitingForDecryptionKeyCB& waiting_for_decryption_key_cb) { init_cb_ = init_cb; output_cb_ = output_cb; @@ -153,9 +155,9 @@ return; } - h264_accelerator_.reset(new D3D11H264Accelerator( - this, video_decoder, video_device_, video_context_)); - decoder_.reset(new media::H264Decoder(h264_accelerator_.get())); + accelerated_video_decoder_ = + std::make_unique<H264Decoder>(std::make_unique<D3D11H264Accelerator>( + this, video_decoder, video_device_, video_context_)); state_ = State::kRunning; std::move(init_cb_).Run(true); @@ -192,7 +194,7 @@ if (current_buffer_->end_of_stream()) { // Flush, then signal the decode cb once all pictures have been output. current_buffer_ = nullptr; - if (!decoder_->Flush()) { + if (!accelerated_video_decoder_->Flush()) { // This will also signal error |current_decode_cb_|. NotifyError("Flush failed"); return; @@ -202,8 +204,8 @@ std::move(current_decode_cb_).Run(DecodeStatus::OK); return; } - decoder_->SetStream((const uint8_t*)current_buffer_->data(), - current_buffer_->data_size()); + accelerated_video_decoder_->SetStream( + (const uint8_t*)current_buffer_->data(), current_buffer_->data_size()); } while (true) { @@ -211,7 +213,8 @@ if (state_ == State::kError) return; - media::AcceleratedVideoDecoder::DecodeResult result = decoder_->Decode(); + media::AcceleratedVideoDecoder::DecodeResult result = + accelerated_video_decoder_->Decode(); // TODO(liberato): switch + class enum. if (result == media::AcceleratedVideoDecoder::kRanOutOfStreamData) { current_buffer_ = nullptr; @@ -248,7 +251,7 @@ input_buffer_queue_.clear(); // TODO(liberato): how do we signal an error? - decoder_->Reset(); + accelerated_video_decoder_->Reset(); closure.Run(); } @@ -272,7 +275,7 @@ // the VDA requests 20. const int num_buffers = 20; - gfx::Size size = decoder_->GetPicSize(); + gfx::Size size = accelerated_video_decoder_->GetPicSize(); // Create an array of |num_buffers| elements to back the PictureBuffers. D3D11_TEXTURE2D_DESC texture_desc = {};
diff --git a/media/gpu/windows/d3d11_video_decoder_impl.h b/media/gpu/windows/d3d11_video_decoder_impl.h index 0a89262..2a2039c 100644 --- a/media/gpu/windows/d3d11_video_decoder_impl.h +++ b/media/gpu/windows/d3d11_video_decoder_impl.h
@@ -33,11 +33,13 @@ // VideoDecoder implementation: std::string GetDisplayName() const override; - void Initialize(const VideoDecoderConfig& config, - bool low_delay, - CdmContext* cdm_context, - const InitCB& init_cb, - const OutputCB& output_cb) override; + void Initialize( + const VideoDecoderConfig& config, + bool low_delay, + CdmContext* cdm_context, + const InitCB& init_cb, + const OutputCB& output_cb, + const WaitingForDecryptionKeyCB& waiting_for_decryption_key_cb) override; void Decode(const scoped_refptr<DecoderBuffer>& buffer, const DecodeCB& decode_cb) override; void Reset(const base::Closure& closure) override; @@ -82,8 +84,7 @@ Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device_; Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context_; - std::unique_ptr<AcceleratedVideoDecoder> decoder_; - std::unique_ptr<D3D11H264Accelerator> h264_accelerator_; + std::unique_ptr<AcceleratedVideoDecoder> accelerated_video_decoder_; GUID decoder_guid_;
diff --git a/media/media_options.gni b/media/media_options.gni index 9d821803..5aa62d6 100644 --- a/media/media_options.gni +++ b/media/media_options.gni
@@ -81,9 +81,6 @@ # If true, use cast CMA backend instead of default chromium media pipeline. is_cast_using_cma_backend = is_cast_audio_only || !is_android - - # A temporary arg for enabling D3D11VideoDecoder - enable_d3d11_video_decoder = false } # enable_hls_sample_aes can only be true if enable_mse_mpeg2ts_stream_parser is. @@ -135,8 +132,8 @@ # |mojo_media_services|). When enabled, selected mojo paths will be enabled in # the media pipeline and corresponding services will hosted in the selected # remote process (e.g. "utility" process, see |mojo_media_host|). - enable_mojo_media = is_android || is_chromecast || enable_library_cdms || - enable_d3d11_video_decoder + enable_mojo_media = + is_android || is_chromecast || enable_library_cdms || is_win # Enable the TestMojoMediaClient to be used in mojo MediaService. This is for # testing only and will override the default platform MojoMediaClient, if any. @@ -203,41 +200,41 @@ # - "gpu": Use mojo media service hosted in the gpu process. # - "utility": Use mojo media service hosted in the utility process. mojo_media_host = "none" +} - # Default mojo_media_services and mojo_media_host on various platforms. - # Can be overridden by gn build arguments from the --args command line flag - # for local testing. - if (enable_mojo_media) { - if (is_chromecast && is_cast_using_cma_backend) { - mojo_media_services = [ - "cdm", - "renderer", - ] - mojo_media_host = "browser" - } else if (is_android) { - # Both chrome for Android and cast for ATV belongs to this case - mojo_media_services = [ - "cdm", - "audio_decoder", - ] - mojo_media_services += [ "video_decoder" ] - mojo_media_host = "gpu" - } else if (enable_library_cdms) { - mojo_media_services = [ "cdm" ] - mojo_media_host = "gpu" - } +# Default mojo_media_services and mojo_media_host on various platforms. +# Can be overridden by gn build arguments from the --args command line flag +# for local testing. +if (enable_mojo_media) { + if (is_chromecast && is_cast_using_cma_backend) { + mojo_media_services = [ + "cdm", + "renderer", + ] + mojo_media_host = "browser" + } else if (is_android) { + # Both chrome for Android and cast for ATV belongs to this case + mojo_media_services = [ + "cdm", + "audio_decoder", + "video_decoder", + ] + mojo_media_host = "gpu" + } else if (is_win) { + mojo_media_services += [ "video_decoder" ] + mojo_media_host = "gpu" + } - if (is_win) { - if (enable_d3d11_video_decoder) { - mojo_media_services += [ - "cdm", - "video_decoder", - ] + if (enable_library_cdms) { + mojo_media_services += [ "cdm" ] + assert( + mojo_media_host == "none" || mojo_media_host == "gpu", + "For now, mojo_media_host should not overwrite it with a different " + + "value if it has been set.") - # TODO(liberato): This is temporary. - mojo_media_host = "gpu" - } - } + # Having a CDM running means it could require a CdmProxy running in the GPU + # process. + mojo_media_host = "gpu" } }
diff --git a/media/mojo/services/gpu_mojo_media_client.cc b/media/mojo/services/gpu_mojo_media_client.cc index 0f37f63..e2ff8b1 100644 --- a/media/mojo/services/gpu_mojo_media_client.cc +++ b/media/mojo/services/gpu_mojo_media_client.cc
@@ -31,9 +31,9 @@ #endif // defined(OS_ANDROID) // OS_WIN guards are needed for cross-compiling on linux. -#if defined(OS_WIN) && BUILDFLAG(ENABLE_D3D11_VIDEO_DECODER) +#if defined(OS_WIN) #include "media/gpu/windows/d3d11_video_decoder.h" -#endif // BUILDFLAG(ENABLE_D3D11_VIDEO_DECODER) +#endif // defined(OS_WIN) namespace media { @@ -61,8 +61,7 @@ } #endif // defined(OS_ANDROID) -#if defined(OS_ANDROID) || \ - (defined(OS_WIN) && BUILDFLAG(ENABLE_D3D11_VIDEO_DECODER)) +#if defined(OS_ANDROID) || defined(OS_WIN) gpu::CommandBufferStub* GetCommandBufferStub( base::WeakPtr<MediaGpuChannelManager> media_gpu_channel_manager, base::UnguessableToken channel_token, @@ -77,7 +76,7 @@ return channel->LookupCommandBuffer(route_id); } -#endif // OS_ANDROID || (OS_WIN && BUILDFLAG(ENABLE_D3D11_VIDEO_DECODER)) +#endif // OS_ANDROID || OS_WIN } // namespace @@ -123,7 +122,7 @@ android_overlay_factory_cb_, std::move(request_overlay_info_cb), std::make_unique<VideoFrameFactoryImpl>(gpu_task_runner_, std::move(get_stub_cb))); -#elif defined(OS_WIN) && BUILDFLAG(ENABLE_D3D11_VIDEO_DECODER) +#elif defined(OS_WIN) return std::make_unique<D3D11VideoDecoder>( gpu_task_runner_, base::BindRepeating(&GetCommandBufferStub, media_gpu_channel_manager_,
diff --git a/net/android/java/src/org/chromium/net/AndroidCellularSignalStrength.java b/net/android/java/src/org/chromium/net/AndroidCellularSignalStrength.java index c5f50d0..ec39f80a 100644 --- a/net/android/java/src/org/chromium/net/AndroidCellularSignalStrength.java +++ b/net/android/java/src/org/chromium/net/AndroidCellularSignalStrength.java
@@ -70,7 +70,14 @@ != ApplicationState.HAS_RUNNING_ACTIVITIES) { return; } - mSignalLevel = signalStrength.getLevel(); + try { + mSignalLevel = signalStrength.getLevel(); + } catch (SecurityException e) { + // Catch any exceptions thrown due to unavailability of permissions on certain + // Android devices. See https://crbug.com/820564 for details. + mSignalLevel = CellularSignalStrengthError.ERROR_NOT_SUPPORTED; + assert false; + } } // ApplicationStatus.ApplicationStateListener
diff --git a/net/proxy_resolution/proxy_config_with_annotation.cc b/net/proxy_resolution/proxy_config_with_annotation.cc index 31ddb8a..b4541ff 100644 --- a/net/proxy_resolution/proxy_config_with_annotation.cc +++ b/net/proxy_resolution/proxy_config_with_annotation.cc
@@ -8,16 +8,17 @@ namespace { -// TODO(rhalavati): Update annotation. constexpr NetworkTrafficAnnotationTag kDirectProxyTrafficAnnotation = DefineNetworkTrafficAnnotation("proxy_config_direct", R"( semantics { sender: "Proxy Config" description: - "This settings create a direct proxy, which practically connects " - "directly to the target website without any intervention." + "Direct connections are being used instead of a proxy. This is a place " + "holder annotation that would include details about where the " + "configuration, which can trigger fetching a PAC file, came from." trigger: - "Direct proxy is the default mode of connection." + "Connecting directly to destination sites instead of using a proxy is " + "the default behavior." data: "None." destination: WEBSITE @@ -25,7 +26,8 @@ policy { cookies_allowed: NO setting: - "Selecting a proxy in settings will prevent use of direct proxy." + "This isn't a real network request. A proxy can be selected in " + "settings." policy_exception_justification: "Using either of 'ProxyMode', 'ProxyServer', or 'ProxyPacUrl' policies " "can set Chrome to use a specific proxy settings and avoid directly "
diff --git a/pdf/run_all_unittests.cc b/pdf/run_all_unittests.cc index 138e5a2..a700cb9 100644 --- a/pdf/run_all_unittests.cc +++ b/pdf/run_all_unittests.cc
@@ -20,5 +20,5 @@ base::TestSuite test_suite(argc, argv); return base::LaunchUnitTests( argc, argv, - base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); + base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite))); }
diff --git a/services/catalog/BUILD.gn b/services/catalog/BUILD.gn index 594b4fb..b47cf5d 100644 --- a/services/catalog/BUILD.gn +++ b/services/catalog/BUILD.gn
@@ -38,7 +38,7 @@ deps = [ ":constants", "//base", - "//components/filesystem:lib", + "//components/services/filesystem:lib", "//services/catalog/public/cpp", "//services/catalog/public/mojom", "//services/service_manager/public/cpp", @@ -46,7 +46,7 @@ public_deps = [ # directory.mojom.h is #included by catalog.h - "//components/filesystem/public/interfaces", + "//components/services/filesystem/public/interfaces", ] }
diff --git a/services/catalog/DEPS b/services/catalog/DEPS index 46b0331..25aecc83 100644 --- a/services/catalog/DEPS +++ b/services/catalog/DEPS
@@ -1,3 +1,3 @@ include_rules = [ - "+components/filesystem" + "+components/services/filesystem" ]
diff --git a/services/catalog/catalog.cc b/services/catalog/catalog.cc index d1763702..71455ef0 100644 --- a/services/catalog/catalog.cc +++ b/services/catalog/catalog.cc
@@ -20,9 +20,9 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/task_scheduler/post_task.h" -#include "components/filesystem/directory_impl.h" -#include "components/filesystem/lock_table.h" -#include "components/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/directory_impl.h" +#include "components/services/filesystem/lock_table.h" +#include "components/services/filesystem/public/interfaces/types.mojom.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/catalog/constants.h" #include "services/catalog/entry_cache.h"
diff --git a/services/catalog/catalog.h b/services/catalog/catalog.h index 8ea3159..1cd8d382 100644 --- a/services/catalog/catalog.h +++ b/services/catalog/catalog.h
@@ -12,7 +12,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "components/filesystem/public/interfaces/directory.mojom.h" +#include "components/services/filesystem/public/interfaces/directory.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/catalog/entry_cache.h"
diff --git a/services/catalog/public/cpp/BUILD.gn b/services/catalog/public/cpp/BUILD.gn index 0fbdf132..febd1d7 100644 --- a/services/catalog/public/cpp/BUILD.gn +++ b/services/catalog/public/cpp/BUILD.gn
@@ -12,7 +12,7 @@ deps = [ "//base", - "//components/filesystem/public/interfaces", + "//components/services/filesystem/public/interfaces", "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", "//services/catalog:constants",
diff --git a/services/catalog/public/cpp/resource_loader.cc b/services/catalog/public/cpp/resource_loader.cc index 90afc1e5..2c106417 100644 --- a/services/catalog/public/cpp/resource_loader.cc +++ b/services/catalog/public/cpp/resource_loader.cc
@@ -9,7 +9,7 @@ #include "base/bind.h" #include "base/files/file.h" -#include "components/filesystem/public/interfaces/directory.mojom.h" +#include "components/services/filesystem/public/interfaces/directory.mojom.h" #include "mojo/public/cpp/system/platform_handle.h" #include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/mojom/interface_provider.mojom.h"
diff --git a/services/catalog/public/cpp/resource_loader.h b/services/catalog/public/cpp/resource_loader.h index 738be36..2ff3221d41 100644 --- a/services/catalog/public/cpp/resource_loader.h +++ b/services/catalog/public/cpp/resource_loader.h
@@ -11,7 +11,7 @@ #include <string> #include "base/macros.h" -#include "components/filesystem/public/interfaces/directory.mojom.h" +#include "components/services/filesystem/public/interfaces/directory.mojom.h" namespace base { class File;
diff --git a/services/file/BUILD.gn b/services/file/BUILD.gn index 0e402e0..1bd2822e 100644 --- a/services/file/BUILD.gn +++ b/services/file/BUILD.gn
@@ -17,10 +17,10 @@ deps = [ "//base", - "//components/filesystem:lib", - "//components/filesystem/public/interfaces", - "//components/leveldb:lib", - "//components/leveldb/public/interfaces", + "//components/services/filesystem:lib", + "//components/services/filesystem/public/interfaces", + "//components/services/leveldb:lib", + "//components/services/leveldb/public/interfaces", "//mojo/common", "//mojo/common:common_base", "//services/file/public/mojom",
diff --git a/services/file/DEPS b/services/file/DEPS index 798ec210..e1577c7 100644 --- a/services/file/DEPS +++ b/services/file/DEPS
@@ -1,4 +1,4 @@ include_rules = [ - "+components/filesystem", - "+components/leveldb", + "+components/services/filesystem", + "+components/services/leveldb", ]
diff --git a/services/file/file_service.cc b/services/file/file_service.cc index 18335a20..c9738152 100644 --- a/services/file/file_service.cc +++ b/services/file/file_service.cc
@@ -8,8 +8,8 @@ #include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" #include "base/task_scheduler/post_task.h" -#include "components/filesystem/lock_table.h" -#include "components/leveldb/leveldb_service_impl.h" +#include "components/services/filesystem/lock_table.h" +#include "components/services/leveldb/leveldb_service_impl.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/file/file_system.h" #include "services/file/user_id_map.h"
diff --git a/services/file/file_service.h b/services/file/file_service.h index 977007c..8cd9814 100644 --- a/services/file/file_service.h +++ b/services/file/file_service.h
@@ -8,8 +8,8 @@ #include "base/callback_forward.h" #include "base/memory/ref_counted.h" #include "base/sequenced_task_runner.h" -#include "components/filesystem/lock_table.h" -#include "components/leveldb/public/interfaces/leveldb.mojom.h" +#include "components/services/filesystem/lock_table.h" +#include "components/services/leveldb/public/interfaces/leveldb.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/file/public/mojom/file_system.mojom.h" #include "services/service_manager/public/cpp/binder_registry.h"
diff --git a/services/file/file_system.cc b/services/file/file_system.cc index 92a41f83..9ec52419 100644 --- a/services/file/file_system.cc +++ b/services/file/file_system.cc
@@ -14,9 +14,9 @@ #include "base/files/scoped_temp_dir.h" #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" -#include "components/filesystem/directory_impl.h" -#include "components/filesystem/lock_table.h" -#include "components/filesystem/public/interfaces/types.mojom.h" +#include "components/services/filesystem/directory_impl.h" +#include "components/services/filesystem/lock_table.h" +#include "components/services/filesystem/public/interfaces/types.mojom.h" #include "mojo/public/cpp/bindings/strong_binding.h" namespace file {
diff --git a/services/file/file_system.h b/services/file/file_system.h index 45dbda27..0e1800b 100644 --- a/services/file/file_system.h +++ b/services/file/file_system.h
@@ -6,7 +6,7 @@ #define SERVICES_FILE_FILE_SYSTEM_H_ #include "base/files/file_path.h" -#include "components/filesystem/public/interfaces/directory.mojom.h" +#include "components/services/filesystem/public/interfaces/directory.mojom.h" #include "services/file/public/mojom/file_system.mojom.h" namespace filesystem {
diff --git a/services/file/public/mojom/BUILD.gn b/services/file/public/mojom/BUILD.gn index 98b0cc0b1..38118ee 100644 --- a/services/file/public/mojom/BUILD.gn +++ b/services/file/public/mojom/BUILD.gn
@@ -10,7 +10,7 @@ ] deps = [ - "//components/filesystem/public/interfaces", + "//components/services/filesystem/public/interfaces", ] public_deps = [
diff --git a/services/file/public/mojom/file_system.mojom b/services/file/public/mojom/file_system.mojom index 2d2659c..e513a8c 100644 --- a/services/file/public/mojom/file_system.mojom +++ b/services/file/public/mojom/file_system.mojom
@@ -4,7 +4,7 @@ module file.mojom; -import "components/filesystem/public/interfaces/directory.mojom"; +import "components/services/filesystem/public/interfaces/directory.mojom"; import "mojo/public/mojom/base/file_error.mojom"; // Provide access to various directories within the requesting user's directory.
diff --git a/services/network/resource_scheduler.cc b/services/network/resource_scheduler.cc index 1d465ac..467a282 100644 --- a/services/network/resource_scheduler.cc +++ b/services/network/resource_scheduler.cc
@@ -1257,6 +1257,11 @@ static const char kNonDelayableWeightBase[] = "NonDelayableWeight"; ParamsForNetworkQualityContainer result; + // Set the default params for networks with ECT Slow2G and 2G. These params + // can still be overridden using the field trial. + result.push_back({net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G, 8, 3}); + result.push_back({net::EFFECTIVE_CONNECTION_TYPE_2G, 8, 3}); + if (!base::FeatureList::IsEnabled(kThrottleDelayable)) return result; @@ -1290,8 +1295,22 @@ return result; } - result.push_back({effective_connection_type.value(), max_delayable_requests, - non_delayable_weight}); + // Check if the entry is already present. This will happen if the default + // params are being overridden by the field trial. + bool entry_found = false; + for (auto& range : result) { + if (effective_connection_type == range.effective_connection_type) { + range.max_delayable_requests = max_delayable_requests; + range.non_delayable_weight = non_delayable_weight; + entry_found = true; + break; + } + } + + if (!entry_found) { + result.push_back({effective_connection_type.value(), + max_delayable_requests, non_delayable_weight}); + } config_param_index++; } }
diff --git a/services/network/resource_scheduler_unittest.cc b/services/network/resource_scheduler_unittest.cc index 99cdd3d..a22bd06b 100644 --- a/services/network/resource_scheduler_unittest.cc +++ b/services/network/resource_scheduler_unittest.cc
@@ -281,7 +281,7 @@ experiment_status, 0.0); // Set the effective connection type to Slow-2G, which is slower than the - // threshold configured in |InitializeMaxDelayableRequestsExperiment|. Needs + // threshold configured in |InitializeThrottleDelayableExperiment|. Needs // to be done before initializing the scheduler because the client is // created on the call to |InitializeScheduler|, which is where the initial // limits for the delayable requests in flight are computed. @@ -303,7 +303,7 @@ EXPECT_TRUE(high2->started()); // Should match the configuration set by - // |InitializeMaxDelayableRequestsExperiment| + // |InitializeThrottleDelayableExperiment| const int kOverriddenNumRequests = 2; std::vector<std::unique_ptr<TestRequest>> lows_singlehost; @@ -366,7 +366,7 @@ experiment_enabled = true; params["EffectiveConnectionType1"] = "Slow-2G"; if (params["MaxDelayableRequests1"] == "") - params["MaxDelayableRequests1"] = "10"; + params["MaxDelayableRequests1"] = "8"; params["NonDelayableWeight1"] = base::NumberToString(non_delayable_weight); } @@ -395,26 +395,38 @@ ResourceScheduler::GetParamsForNetworkQualityContainerForTests(); if (!lower_delayable_count_enabled && non_delayable_weight <= 0.0) { - ASSERT_EQ(0u, params_network_quality_container.size()); + ASSERT_EQ(2u, params_network_quality_container.size()); + EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G, + params_network_quality_container[0].effective_connection_type); + EXPECT_EQ(8u, params_network_quality_container[0].max_delayable_requests); + EXPECT_EQ(3.0, params_network_quality_container[0].non_delayable_weight); + + EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, + params_network_quality_container[1].effective_connection_type); + EXPECT_EQ(8u, params_network_quality_container[1].max_delayable_requests); + EXPECT_EQ(3.0, params_network_quality_container[1].non_delayable_weight); return; } // Check that the configuration was parsed and stored correctly. - ASSERT_EQ(lower_delayable_count_enabled ? 2u : 1u, + ASSERT_EQ(lower_delayable_count_enabled ? 3u : 2u, params_network_quality_container.size()); EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G, params_network_quality_container[0].effective_connection_type); - EXPECT_EQ(non_delayable_weight > 0.0 ? 10u : 2u, + EXPECT_EQ(non_delayable_weight > 0.0 ? 8u : 2u, params_network_quality_container[0].max_delayable_requests); EXPECT_EQ(non_delayable_weight > 0.0 ? non_delayable_weight : 0.0, params_network_quality_container[0].non_delayable_weight); + EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, + params_network_quality_container[1].effective_connection_type); + if (lower_delayable_count_enabled) { EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_3G, - params_network_quality_container[1].effective_connection_type); - EXPECT_EQ(4u, params_network_quality_container[1].max_delayable_requests); - EXPECT_EQ(0.0, params_network_quality_container[1].non_delayable_weight); + params_network_quality_container[2].effective_connection_type); + EXPECT_EQ(4u, params_network_quality_container[2].max_delayable_requests); + EXPECT_EQ(0.0, params_network_quality_container[2].non_delayable_weight); } } @@ -450,23 +462,38 @@ ResourceScheduler::GetParamsForNetworkQualityContainerForTests(); // Check that the configuration was parsed and stored correctly. - ASSERT_EQ(params_network_quality_container.size(), num_ranges); - for (size_t index = 1; index <= num_ranges; index++) { + ASSERT_EQ(std::max(static_cast<size_t>(2u), num_ranges), + params_network_quality_container.size()); + for (size_t index = 1; index <= params_network_quality_container.size(); + index++) { EXPECT_EQ(1 + index, static_cast<size_t>(params_network_quality_container[index - 1] .effective_connection_type)); - EXPECT_EQ( - index * 10u, - params_network_quality_container[index - 1].max_delayable_requests); - EXPECT_EQ( - 0, params_network_quality_container[index - 1].non_delayable_weight); + if (params_network_quality_container[index - 1] + .effective_connection_type <= + net::EFFECTIVE_CONNECTION_TYPE_2G && + num_ranges < index) { + EXPECT_EQ( + 8u, + params_network_quality_container[index - 1].max_delayable_requests); + EXPECT_EQ( + 3, + params_network_quality_container[index - 1].non_delayable_weight); + } else { + EXPECT_EQ( + index * 10u, + params_network_quality_container[index - 1].max_delayable_requests); + EXPECT_EQ( + 0, + params_network_quality_container[index - 1].non_delayable_weight); + } } } void NonDelayableThrottlesDelayableHelper(double non_delayable_weight) { base::test::ScopedFeatureList scoped_feature_list; - // Should be in sync with .cc. - const int kDefaultMaxNumDelayableRequestsPerClient = 10; + // Should be in sync with .cc for ECT SLOW_2G, + const int kDefaultMaxNumDelayableRequestsPerClient = 8; // Initialize the experiment. InitializeThrottleDelayableExperiment(&scoped_feature_list, false, non_delayable_weight); @@ -1598,7 +1625,7 @@ EXPECT_TRUE(high->started()); // Should be based on the value set by - // |InitializeMaxDelayableRequestsExperiment| for the given range. + // |InitializeThrottleDelayableExperiment| for the given range. const int kOverriddenNumRequests = 2; std::vector<std::unique_ptr<TestRequest>> lows_singlehost; @@ -1791,11 +1818,16 @@ // Only the first configuration parameter must be read because a match was not // found for index 2. The configuration parameters with index 3 and 4 must be // ignored, even though they are valid configuration parameters. - EXPECT_EQ(1u, params_network_quality_container.size()); + EXPECT_EQ(2u, params_network_quality_container.size()); EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G, params_network_quality_container[0].effective_connection_type); EXPECT_EQ(10u, params_network_quality_container[0].max_delayable_requests); EXPECT_EQ(0.0, params_network_quality_container[0].non_delayable_weight); + + EXPECT_EQ(net::EFFECTIVE_CONNECTION_TYPE_2G, + params_network_quality_container[1].effective_connection_type); + EXPECT_EQ(8u, params_network_quality_container[1].max_delayable_requests); + EXPECT_EQ(3.0, params_network_quality_container[1].non_delayable_weight); } // Test that the default limit is used for delayable requests when the @@ -1841,7 +1873,7 @@ base::test::ScopedFeatureList scoped_feature_list; const double kNonDelayableWeight = 2.0; const int kDefaultMaxNumDelayableRequestsPerClient = - 10; // Should be in sync with cc. + 8; // Should be in sync with cc. // Initialize the experiment with |kNonDelayableWeight| as the weight of // non-delayable requests. InitializeThrottleDelayableExperiment(&scoped_feature_list, false, @@ -1879,12 +1911,6 @@ } } -// Test that the default limit is used for delayable requests in the presence of -// non-delayable requests when the non-delayable request weight is zero. -TEST_F(ResourceSchedulerTest, NonDelayableThrottlesDelayableWeight0) { - NonDelayableThrottlesDelayableHelper(0.0); -} - // Test that each non-delayable request in-flight results in the reduction of // one in the limit of delayable requests in-flight when the non-delayable // request weight is 1.
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index 08242a6..c88a5d7a6 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef SkUserConfig_DEFINED -#define SkUserConfig_DEFINED +#ifndef SKIA_CONFIG_SKUSERCONFIG_H_ +#define SKIA_CONFIG_SKUSERCONFIG_H_ /* SkTypes.h, the root of the public header files, does the following trick: @@ -213,10 +213,6 @@ #define SK_LEGACY_GPU_PIXEL_OPS #endif -#ifndef SK_SUPPORT_LEGACY_BLURMASKFILTER -#define SK_SUPPORT_LEGACY_BLURMASKFILTER -#endif - #ifndef SK_SUPPORT_LEGACY_YUV_COLORSPACE #define SK_SUPPORT_LEGACY_YUV_COLORSPACE #endif
diff --git a/sql/test/run_all_unittests.cc b/sql/test/run_all_unittests.cc index 85ceac0..bdbe97b 100644 --- a/sql/test/run_all_unittests.cc +++ b/sql/test/run_all_unittests.cc
@@ -10,7 +10,6 @@ sql::SQLTestSuite test_suite(argc, argv); return base::LaunchUnitTests( - argc, - argv, - base::Bind(&sql::SQLTestSuite::Run, base::Unretained(&test_suite))); + argc, argv, + base::BindOnce(&sql::SQLTestSuite::Run, base::Unretained(&test_suite))); }
diff --git a/testing/buildbot/filters/viz.browser_tests.filter b/testing/buildbot/filters/viz.browser_tests.filter index 8ed9070e..c74a371 100644 --- a/testing/buildbot/filters/viz.browser_tests.filter +++ b/testing/buildbot/filters/viz.browser_tests.filter
@@ -101,3 +101,10 @@ # Unknown Flakes # Flaky timeouts. http://crbug.com/807773 -PDFExtensionClipboardTest.* + +# Windows timeouts. https://crbug.com/821029 +-ManifestVerifierBrowserTest.* +-PrefHashBrowserTest* +-UserInitiatedRunsDisabled* +-UserInitiatedRunsEnabled* +-WithVaryingSeeds/ChromeCleanerPromptUserTest.*
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 5932335b..1776d9f8 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -527,7 +527,7 @@ "type": "windowed_test_launcher", }, "filesystem_service_unittests": { - "label": "//components/filesystem:filesystem_service_unittests", + "label": "//components/services/filesystem:filesystem_service_unittests", "type": "console_test_launcher", }, "gcm_unit_tests": { @@ -739,7 +739,7 @@ "type": "console_test_launcher", }, "leveldb_service_unittests": { - "label": "//components/leveldb:leveldb_service_unittests", + "label": "//components/services/leveldb:leveldb_service_unittests", "type": "console_test_launcher", }, "libjingle_xmpp_unittests": {
diff --git a/testing/libfuzzer/fuzzers/string_to_int_fuzzer.cc b/testing/libfuzzer/fuzzers/string_to_int_fuzzer.cc index ca42f67..59aff298 100644 --- a/testing/libfuzzer/fuzzers/string_to_int_fuzzer.cc +++ b/testing/libfuzzer/fuzzers/string_to_int_fuzzer.cc
@@ -12,26 +12,30 @@ // Entry point for LibFuzzer. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - std::string input(reinterpret_cast<const char*>(data), size); - int out_int; - base::StringToInt(input, &out_int); - unsigned out_uint; - base::StringToUint(input, &out_uint); - int64_t out_int64; - base::StringToInt64(input, &out_int64); - uint64_t out_uint64; - base::StringToUint64(input, &out_uint64); - size_t out_size; - base::StringToSizeT(input, &out_size); - double out_double; - base::StringToDouble(input, &out_double); - base::HexStringToInt(input, &out_int); - base::HexStringToUInt(input, &out_uint); - base::HexStringToInt64(input, &out_int64); - base::HexStringToUInt64(input, &out_uint64); + base::StringPiece string_piece_input(reinterpret_cast<const char*>(data), + size); + std::string string_input(reinterpret_cast<const char*>(data), size); + int out_int; + base::StringToInt(string_piece_input, &out_int); + unsigned out_uint; + base::StringToUint(string_piece_input, &out_uint); + int64_t out_int64; + base::StringToInt64(string_piece_input, &out_int64); + uint64_t out_uint64; + base::StringToUint64(string_piece_input, &out_uint64); + size_t out_size; + base::StringToSizeT(string_piece_input, &out_size); + + double out_double; + base::StringToDouble(string_input, &out_double); + + base::HexStringToInt(string_piece_input, &out_int); + base::HexStringToUInt(string_piece_input, &out_uint); + base::HexStringToInt64(string_piece_input, &out_int64); + base::HexStringToUInt64(string_piece_input, &out_uint64); std::vector<uint8_t> out_bytes; - base::HexStringToBytes(input, &out_bytes); + base::HexStringToBytes(string_piece_input, &out_bytes); base::HexEncode(data, size); return 0;
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 877dd32..343cc2c 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -3693,15 +3693,9 @@ { "name": "Enabled", "params": { - "EffectiveConnectionType1": "Slow-2G", - "EffectiveConnectionType2": "2G", - "EffectiveConnectionType3": "3G", - "MaxDelayableRequests1": "8", - "MaxDelayableRequests2": "8", - "MaxDelayableRequests3": "14", - "NonDelayableWeight1": "2.0", - "NonDelayableWeight2": "2.0", - "NonDelayableWeight3": "2.0" + "EffectiveConnectionType1": "3G", + "MaxDelayableRequests1": "14", + "NonDelayableWeight1": "2.0" }, "enable_features": [ "ThrottleDelayable"
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 42f3000..227f8724 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -97,7 +97,7 @@ crbug.com/591099 animations/animation-ready-reject-script-forbidden.html [ Timeout ] crbug.com/591099 animations/cross-fade-list-style-image.html [ Failure ] crbug.com/591099 animations/interpolation/backdrop-filter-interpolation.html [ Timeout ] -crbug.com/591099 animations/interpolation/line-height-interpolation.html [ Pass Timeout ] +crbug.com/591099 animations/interpolation/line-height-interpolation.html [ Timeout ] crbug.com/591099 animations/interpolation/svg-stroke-dasharray-interpolation.html [ Timeout ] crbug.com/591099 animations/interpolation/webkit-clip-path-interpolation.html [ Pass Timeout ] crbug.com/591099 animations/interpolation/webkit-column-width-interpolation.html [ Pass ] @@ -106,14 +106,12 @@ crbug.com/714962 compositing/background-color/view-blending-base-background.html [ Failure ] crbug.com/591099 compositing/draws-content/canvas-background-layer.html [ Failure ] crbug.com/591099 compositing/draws-content/webgl-background-layer.html [ Failure ] -crbug.com/591099 compositing/generated-content.html [ Failure Pass ] crbug.com/591099 compositing/geometry/bounds-ignores-hidden-dynamic.html [ Failure ] crbug.com/591099 compositing/geometry/bounds-ignores-hidden.html [ Failure ] crbug.com/591099 compositing/geometry/clipping-foreground.html [ Failure ] crbug.com/591099 compositing/geometry/composited-in-columns.html [ Failure ] crbug.com/591099 compositing/geometry/foreground-layer.html [ Failure ] crbug.com/591099 compositing/geometry/repaint-foreground-layer.html [ Failure ] -crbug.com/591099 compositing/geometry/transfrom-origin-on-zero-size-layer.html [ Failure Pass ] crbug.com/591099 compositing/geometry/video-opacity-overlay.html [ Failure ] crbug.com/714962 compositing/gestures/gesture-tapHighlight-2-overflow-div-scrolled-inner.html [ Failure ] crbug.com/714962 compositing/gestures/gesture-tapHighlight-simple-multi-line.html [ Pass ] @@ -126,12 +124,9 @@ crbug.com/591099 compositing/overflow/nested-border-radius-clipping.html [ Failure ] crbug.com/591099 compositing/overflow/overflow-scroll-with-local-image-background.html [ Failure ] crbug.com/714962 compositing/overflow/rtl-overflow.html [ Failure ] -crbug.com/591099 compositing/overflow/scaled-mask.html [ Failure Pass ] crbug.com/591099 compositing/overflow/scrolling-content-clip-to-viewport.html [ Failure ] crbug.com/591099 compositing/overflow/universal-accelerated-overflow-scroll.html [ Timeout ] crbug.com/591099 compositing/overflow/update-widget-positions-on-nested-frames-and-scrollers.html [ Failure ] -crbug.com/591099 compositing/reflections/compositing-change-inside-reflection.html [ Failure Pass ] -crbug.com/591099 compositing/reflections/transform-inside-reflection.html [ Failure Pass ] crbug.com/591099 compositing/rtl/rtl-and-writing-mode-scrolling.html [ Failure ] crbug.com/591099 compositing/scrollbars/nested-overlay-scrollbars.html [ Failure ] crbug.com/591099 compositing/squashing/add-remove-squashed-layers.html [ Failure ] @@ -199,7 +194,6 @@ crbug.com/591099 editing/caret/caret-color-014.html [ Failure ] crbug.com/591099 editing/caret/caret-color-015.html [ Failure ] crbug.com/591099 editing/deleting/5272440.html [ Failure ] -crbug.com/591099 editing/deleting/5369009.html [ Failure Pass ] crbug.com/591099 editing/deleting/delete-at-paragraph-boundaries-011.html [ Failure ] crbug.com/591099 editing/deleting/merge-different-styles.html [ Failure ] crbug.com/591099 editing/deleting/merge-endOfParagraph.html [ Failure ] @@ -217,10 +211,8 @@ crbug.com/591099 editing/execCommand/format-block-multiple-paragraphs-in-pre.html [ Failure ] crbug.com/591099 editing/execCommand/format-block-multiple-paragraphs.html [ Failure ] crbug.com/591099 editing/execCommand/insertImage.html [ Failure ] -crbug.com/591099 editing/execCommand/query-command-state.html [ Pass Timeout ] crbug.com/591099 editing/execCommand/query-format-block.html [ Timeout ] crbug.com/591099 editing/execCommand/remove-list-from-range-selection.html [ Failure ] -crbug.com/591099 editing/input/linux_rtl_composition_underline.html [ Failure Pass ] crbug.com/591099 editing/inserting/4875189-1.html [ Failure ] crbug.com/591099 editing/inserting/4959067.html [ Failure ] crbug.com/591099 editing/inserting/editable-inline-element.html [ Failure ] @@ -235,7 +227,6 @@ crbug.com/591099 editing/inserting/paragraph-separator-in-table-1.html [ Failure ] crbug.com/591099 editing/inserting/paragraph-separator-in-table-2.html [ Failure ] crbug.com/591099 editing/pasteboard/4631972.html [ Failure ] -crbug.com/591099 editing/pasteboard/5071074.html [ Failure Pass ] crbug.com/591099 editing/pasteboard/bad-placeholder.html [ Failure ] crbug.com/714962 editing/pasteboard/copy-element-with-conflicting-background-color-from-rule.html [ Failure ] crbug.com/714962 editing/pasteboard/copy-paste-pre-line-content.html [ Failure ] @@ -283,7 +274,7 @@ crbug.com/591099 editing/selection/extend-selection-bidi.html [ Failure ] crbug.com/591099 editing/selection/extend-selection-character.html [ Timeout ] crbug.com/591099 editing/selection/extend-selection-home-end.html [ Timeout ] -crbug.com/591099 editing/selection/extend-selection-word.html [ Timeout ] +crbug.com/591099 editing/selection/extend-selection-word.html [ Pass Timeout ] crbug.com/591099 editing/selection/focus-body.html [ Failure ] crbug.com/591099 editing/selection/home-end.html [ Timeout ] crbug.com/591099 editing/selection/line-wrap-2.html [ Failure ] @@ -360,6 +351,7 @@ crbug.com/591099 external/wpt/compat/webkit-text-fill-color-property-005.html [ Pass ] crbug.com/591099 external/wpt/credential-management/federatedcredential-framed-get.sub.https.html [ Pass ] crbug.com/591099 external/wpt/credential-management/passwordcredential-framed-get.sub.https.html [ Pass ] +crbug.com/591099 external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins-no-clearance.html [ Pass ] crbug.com/591099 external/wpt/css/CSS2/floats/floats-rule3-outside-left-002.xht [ Pass ] crbug.com/714962 external/wpt/css/CSS2/linebox/vertical-align-baseline-005a.xht [ Failure ] crbug.com/591099 external/wpt/css/CSS2/normal-flow/block-in-inline-insert-001e.xht [ Pass ] @@ -373,7 +365,6 @@ crbug.com/591099 external/wpt/css/CSS2/normal-flow/root-box-001.xht [ Failure ] crbug.com/591099 external/wpt/css/CSS2/positioning/abspos-007.xht [ Pass ] crbug.com/591099 external/wpt/css/CSS2/positioning/positioning-float-001.xht [ Pass ] -crbug.com/591099 external/wpt/css/CSS2/text/text-decoration-applies-to-015.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Failure ] crbug.com/714962 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-image-5.html [ Failure ] crbug.com/591099 external/wpt/css/css-backgrounds/box-shadow-syntax-001.xht [ Failure ] @@ -777,71 +768,122 @@ crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vrl-018.xht [ Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vrl-020.xht [ Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vrl-030.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-005.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-017.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-029.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-041.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-053.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-065.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-077.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-089.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-095.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-105.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-109.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-121.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-125.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-137.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-141.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-153.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-157.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-169.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-173.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-185.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-189.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-201.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-205.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-217.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-221.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-225.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-229.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-002.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-004.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-006.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-008.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-010.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-012.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-014.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-016.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-018.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-020.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-024.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-026.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-028.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-030.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-032.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-034.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-036.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-038.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-040.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-042.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-044.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-048.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-050.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-052.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-054.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-056.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-060.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-064.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-066.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-072.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-074.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-076.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-078.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-080.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-084.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-086.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-088.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-090.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-092.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-096.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-102.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-104.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-106.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-108.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-110.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-112.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-114.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-116.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-118.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-122.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-124.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-126.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-128.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-130.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-132.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-136.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-138.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-140.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-142.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-144.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-146.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-148.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-150.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-154.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-156.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-158.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-160.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-162.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-164.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-170.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-172.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-176.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-178.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-186.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-188.xht [ Pass ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-192.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-194.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-198.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-202.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-204.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-206.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-208.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-210.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-212.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-214.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-218.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-220.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-222.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-224.xht [ Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-226.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-228.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/available-size-001.html [ Failure ] @@ -1017,7 +1059,7 @@ crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/selectors4/dir-style-03a.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-declaration-15.html [ Failure Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-font-face-01.html [ Failure Pass ] -crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-font-face-02.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-font-face-02.html [ Failure ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-break-inside-001.html [ Failure ] crbug.com/591099 external/wpt/dom/interfaces.html [ Timeout ] crbug.com/591099 external/wpt/dom/nodes/Document-contentType/contentType/contenttype_datauri_02.html [ Pass ] @@ -1161,7 +1203,7 @@ crbug.com/591099 external/wpt/encoding/textdecoder-fatal-single-byte.html [ Timeout ] crbug.com/591099 external/wpt/feature-policy/payment-allowed-by-feature-policy.https.sub.html [ Pass ] crbug.com/591099 external/wpt/feature-policy/payment-disabled-by-feature-policy.https.sub.html [ Pass ] -crbug.com/591099 external/wpt/fetch/api/request/request-cache-default-conditional.html [ Timeout ] +crbug.com/591099 external/wpt/fetch/api/request/request-cache-default-conditional.html [ Pass Timeout ] crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure Pass ] crbug.com/591099 external/wpt/html-media-capture/capture_audio_cancel-manual.html [ Failure ] crbug.com/591099 external/wpt/html-media-capture/capture_image_cancel-manual.html [ Failure ] @@ -1227,7 +1269,7 @@ crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html [ Timeout ] crbug.com/591099 external/wpt/pointerevents/pointerevent_touch-action-button-test_touch-manual.html [ Timeout ] crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-keyboard-manual.html [ Timeout ] -crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-mouse-manual.html [ Timeout ] +crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-mouse-manual.html [ Pass Timeout ] crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-pan-left-css_touch-manual.html [ Pass ] crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-pan-right-css_touch-manual.html [ Failure ] crbug.com/714962 external/wpt/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html [ Timeout ] @@ -1368,17 +1410,14 @@ crbug.com/591099 fast/backgrounds/background-clip-text.html [ Failure ] crbug.com/591099 fast/backgrounds/background-inherit-color-bug.html [ Failure ] crbug.com/591099 fast/backgrounds/background-leakage-transforms.html [ Failure ] -crbug.com/591099 fast/backgrounds/background-origin-root-element.html [ Failure Pass ] crbug.com/591099 fast/backgrounds/border-radius-split-background-image.html [ Failure ] crbug.com/591099 fast/backgrounds/border-radius-split-background.html [ Failure ] -crbug.com/591099 fast/backgrounds/opacity-on-document-element.html [ Failure Pass ] crbug.com/591099 fast/backgrounds/quirks-mode-line-box-backgrounds.html [ Failure ] crbug.com/591099 fast/backgrounds/repeat/noRepeatCorrectClip.html [ Failure ] crbug.com/591099 fast/backgrounds/selection-background-color-of-image-list-style.html [ Failure ] crbug.com/591099 fast/backgrounds/selection-background-color-of-list-style.html [ Failure ] crbug.com/591099 fast/backgrounds/size/backgroundSize16.html [ Failure ] crbug.com/591099 fast/backgrounds/size/contain-and-cover.html [ Failure ] -crbug.com/591099 fast/backgrounds/size/zero.html [ Failure Pass ] crbug.com/591099 fast/block/basic/quirk-percent-height-table-cell.html [ Failure ] crbug.com/591099 fast/block/block-add-child-crash.html [ Crash ] crbug.com/591099 fast/block/block-width-recalc-with-relative-height.html [ Failure ] @@ -1424,7 +1463,6 @@ crbug.com/591099 fast/borders/border-antialiasing.html [ Failure ] crbug.com/591099 fast/borders/border-image-border-radius.html [ Failure ] crbug.com/714962 fast/borders/border-image-outset-split-inline.html [ Failure ] -crbug.com/714962 fast/borders/border-image-scaled.html [ Failure Pass ] crbug.com/714962 fast/borders/border-inner-bleed.html [ Failure ] crbug.com/714962 fast/borders/border-radius-inline-flow.html [ Failure ] crbug.com/591099 fast/borders/border-radius-mask-canvas-all.html [ Failure ] @@ -1454,7 +1492,6 @@ crbug.com/714962 fast/borders/borderRadiusSolid03.html [ Failure ] crbug.com/714962 fast/borders/borderRadiusSolid04.html [ Failure ] crbug.com/714962 fast/borders/dashed-1px-with-border-radius.html [ Failure ] -crbug.com/714962 fast/borders/different-color-borders.html [ Failure Pass ] crbug.com/591099 fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ] crbug.com/591099 fast/borders/inline-mask-overlay-image-outset.html [ Failure ] crbug.com/591099 fast/borders/inline-mask-overlay-image.html [ Failure ] @@ -1470,22 +1507,13 @@ crbug.com/591099 fast/box-shadow/inset-subpixel.html [ Failure ] crbug.com/591099 fast/box-shadow/inset.html [ Failure ] crbug.com/591099 fast/box-sizing/replaced.html [ Failure ] -crbug.com/714962 fast/canvas/canvas-textMetrics-width.html [ Failure Pass ] -crbug.com/714962 fast/canvas/image-object-in-canvas.html [ Failure Pass ] -crbug.com/591099 fast/canvas/patternfill-repeat.html [ Failure Pass ] -crbug.com/714962 fast/canvas/setWidthResetAfterForcedRender.html [ Failure Pass ] crbug.com/591099 fast/clip/overflow-border-radius-combinations.html [ Failure ] crbug.com/591099 fast/clip/overflow-border-radius-composited-parent.html [ Failure ] crbug.com/591099 fast/clip/overflow-border-radius-composited.html [ Failure ] -crbug.com/591099 fast/clip/overflow-border-radius-fixed-position.html [ Failure Pass ] crbug.com/591099 fast/clip/overflow-border-radius-transformed.html [ Failure ] -crbug.com/591099 fast/css-generated-content/001.html [ Failure Pass ] -crbug.com/591099 fast/css-generated-content/007.html [ Failure Pass ] crbug.com/591099 fast/css-generated-content/009.html [ Failure ] crbug.com/591099 fast/css-generated-content/012.html [ Failure ] -crbug.com/591099 fast/css-generated-content/013.html [ Failure Pass ] crbug.com/591099 fast/css-generated-content/015.html [ Failure ] -crbug.com/591099 fast/css-generated-content/after-duplicated-after-split.html [ Failure Pass ] crbug.com/805301 fast/css-generated-content/crash-selection-editing-removes-pseudo.html [ Failure ] crbug.com/591099 fast/css-generated-content/empty-first-letter-with-columns-crash.html [ Crash ] crbug.com/591099 fast/css-generated-content/first-letter-next-sibling-crash.html [ Crash ] @@ -1493,6 +1521,7 @@ crbug.com/714962 fast/css-generated-content/hover-inline.html [ Failure ] crbug.com/591099 fast/css-generated-content/table-before-after-child-add.html [ Failure ] crbug.com/591099 fast/css-generated-content/table-cell-before-after-child-add.html [ Failure ] +crbug.com/591099 fast/css-generated-content/table-parts-before-and-after.html [ Crash ] crbug.com/591099 fast/css-generated-content/table-row-before-after-child-add.html [ Failure ] crbug.com/591099 fast/css-generated-content/table-row-group-to-inline.html [ Failure ] crbug.com/591099 fast/css-generated-content/table-row-group-with-before.html [ Failure ] @@ -1588,7 +1617,7 @@ crbug.com/591099 fast/css-grid-layout/minmax-min-content-column-resolution-rows.html [ Failure ] crbug.com/591099 fast/css-grid-layout/minmax-spanning-resolution-columns.html [ Failure ] crbug.com/591099 fast/css-grid-layout/minmax-spanning-resolution-rows.html [ Failure ] -crbug.com/591099 fast/css-grid-layout/named-grid-line-get-set.html [ Timeout ] +crbug.com/591099 fast/css-grid-layout/named-grid-line-get-set.html [ Pass Timeout ] crbug.com/591099 fast/css-grid-layout/named-grid-lines-with-named-grid-areas-dynamic-get-set.html [ Failure ] crbug.com/591099 fast/css-grid-layout/named-grid-lines-with-named-grid-areas-resolution.html [ Failure ] crbug.com/591099 fast/css-grid-layout/percent-grid-item-in-percent-grid-track-in-percent-grid.html [ Failure ] @@ -1683,13 +1712,10 @@ crbug.com/591099 fast/css/word-space-extra.html [ Failure ] crbug.com/714962 fast/css3-text/css3-text-decoration/repaint/repaint-text-decoration-style.html [ Failure ] crbug.com/591099 fast/css3-text/css3-text-decoration/text-decoration-skip-ink.html [ Failure ] -crbug.com/591099 fast/css3-text/css3-text-decoration/text-decoration-style-inherit-not-propagated-by-out-of-flow.html [ Failure Pass ] -crbug.com/714962 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-all.html [ Failure Pass ] crbug.com/591099 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-auto.html [ Failure ] crbug.com/591099 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-cjk.html [ Failure ] crbug.com/714962 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-dynamic.html [ Failure ] crbug.com/714962 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-subscript.html [ Failure ] -crbug.com/714962 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-under-out-of-flow.html [ Failure Pass ] crbug.com/714962 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-under-vertical.html [ Failure ] crbug.com/591099 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-under.html [ Failure ] crbug.com/591099 fast/css3-text/css3-text-indent/negative-text-indent-leading-out-of-flow-text-align-left-and-right.html [ Failure ] @@ -1699,9 +1725,6 @@ crbug.com/591099 fast/css3-text/css3-text-justify/text-justify-distribute.html [ Failure ] crbug.com/591099 fast/deprecated-flexbox/004.html [ Failure ] crbug.com/591099 fast/deprecated-flexbox/009-horizontal.html [ Failure ] -crbug.com/714962 fast/deprecated-flexbox/009.html [ Failure Pass ] -crbug.com/714962 fast/deprecated-flexbox/023.html [ Failure Pass ] -crbug.com/714962 fast/deprecated-flexbox/024.html [ Failure Pass ] crbug.com/591099 fast/deprecated-flexbox/flexing-overflow-scroll-item.html [ Failure ] crbug.com/591099 fast/deprecated-flexbox/relpos-flex-item-with-percent-height-abspos-child.html [ Failure ] crbug.com/591099 fast/deprecated-flexbox/relpos-flex-item-with-percent-height-abspos-descendant.html [ Failure ] @@ -1715,8 +1738,6 @@ crbug.com/714962 fast/dom/Element/getClientRects.html [ Failure ] crbug.com/591099 fast/dom/HTMLMeterElement/meter-boundary-values.html [ Failure ] crbug.com/591099 fast/dom/HTMLMeterElement/meter-optimums.html [ Failure ] -crbug.com/591099 fast/dom/HTMLMeterElement/meter-styles.html [ Failure Pass ] -crbug.com/591099 fast/dom/HTMLObjectElement/vspace-hspace-as-number.html [ Failure Pass ] crbug.com/591099 fast/dom/HTMLProgressElement/progress-bar-value-pseudo-element.html [ Failure ] crbug.com/714962 fast/dom/Range/collapsed-range-bounding-client-rect.html [ Failure ] crbug.com/714962 fast/dom/Range/get-bounding-client-rect-empty-and-non-empty.html [ Timeout ] @@ -1752,8 +1773,6 @@ crbug.com/591099 fast/dom/wrapper-classes.html [ Timeout ] crbug.com/591099 fast/dynamic/continuation-detach-crash.html [ Crash ] crbug.com/591099 fast/dynamic/first-letter-after-list-marker.html [ Failure ] -crbug.com/591099 fast/dynamic/layer-hit-test-crash.html [ Failure Pass ] -crbug.com/591099 fast/dynamic/outerHTML-img.html [ Failure Pass ] crbug.com/591099 fast/dynamic/selection-highlight-adjust.html [ Failure ] crbug.com/591099 fast/dynamic/static-to-relative-with-absolute-child.html [ Crash ] crbug.com/591099 fast/dynamic/text-combine.html [ Failure ] @@ -1776,7 +1795,7 @@ crbug.com/591099 fast/events/pointerevents/mouse-pointer-capture.html [ Timeout ] crbug.com/591099 fast/events/pointerevents/mouse-pointer-event-properties.html [ Timeout ] crbug.com/591099 fast/events/pointerevents/mouse-pointer-preventdefault.html [ Timeout ] -crbug.com/591099 fast/events/pointerevents/multi-pointer-preventdefault.html [ Timeout ] +crbug.com/591099 fast/events/pointerevents/multi-pointer-preventdefault.html [ Pass Timeout ] crbug.com/591099 fast/events/pointerevents/touch-capture-in-iframe.html [ Timeout ] crbug.com/591099 fast/events/pointerevents/touch-capture.html [ Timeout ] crbug.com/714962 fast/events/pointerevents/touch-pointer-events.html [ Pass ] @@ -1836,10 +1855,8 @@ crbug.com/591099 fast/forms/textarea/textarea-resize-orthogonal-containing-block.html [ Pass ] crbug.com/591099 fast/forms/time-multiple-fields/time-multiple-fields-stepup-stepdown-from-renderer.html [ Timeout ] crbug.com/591099 fast/frames/iframe-with-frameborder.html [ Failure ] -crbug.com/591099 fast/gradients/generated-gradients.html [ Failure Pass ] crbug.com/591099 fast/gradients/list-item-gradient.html [ Failure ] crbug.com/591099 fast/gradients/radial-centered.html [ Failure ] -crbug.com/591099 fast/gradients/simple-gradients.html [ Failure Pass ] crbug.com/591099 fast/gradients/unprefixed-list-item-gradient.html [ Failure ] crbug.com/591099 fast/hidpi/broken-image-icon-hidpi.html [ Failure ] crbug.com/591099 fast/hidpi/image-set-list-style-image.html [ Failure ] @@ -1872,11 +1889,6 @@ crbug.com/591099 fast/inline/outline-continuations.html [ Failure ] crbug.com/714962 fast/inline/outline-offset.html [ Failure ] crbug.com/591099 fast/inline/styledEmptyInlinesWithBRs.html [ Failure ] -crbug.com/591099 fast/invalid/010.html [ Failure Pass ] -crbug.com/591099 fast/invalid/missing-address-end-tag.html [ Failure Pass ] -crbug.com/591099 fast/invalid/missing-dl-end-tag.html [ Failure Pass ] -crbug.com/591099 fast/invalid/missing-dt-end-tag.html [ Failure Pass ] -crbug.com/591099 fast/invalid/missing-font-end-tag.html [ Failure Pass ] crbug.com/591099 fast/js/dfg-arguments-alias-activation.html [ Timeout ] crbug.com/591099 fast/js/dfg-byte-array-put.html [ Timeout ] crbug.com/591099 fast/js/document-all-triggers-masquerades-watchpoint.html [ Timeout ] @@ -1898,7 +1910,6 @@ crbug.com/591099 fast/lists/calc-width-with-space.html [ Failure ] crbug.com/591099 fast/lists/drag-into-marker.html [ Failure ] crbug.com/591099 fast/lists/inline-before-content-after-list-marker.html [ Failure ] -crbug.com/591099 fast/lists/li-with-overflow-hidden-change-list-style-position.html [ Failure Pass ] crbug.com/591099 fast/lists/list-color-change-no-layout.html [ Failure ] crbug.com/591099 fast/lists/list-inside-columns-crash.html [ Crash ] crbug.com/591099 fast/lists/list-item-line-height.html [ Failure ] @@ -2316,7 +2327,6 @@ crbug.com/714962 fast/overflow/childFocusRingClip.html [ Failure ] crbug.com/591099 fast/overflow/height-during-simplified-layout.html [ Failure ] crbug.com/591099 fast/overflow/image-selection-highlight.html [ Failure ] -crbug.com/591099 fast/overflow/infiniteRecursion.html [ Failure Pass ] crbug.com/714962 fast/overflow/line-clamp-hides-trailing-anchor.html [ Failure ] crbug.com/591099 fast/overflow/line-clamp.html [ Failure ] crbug.com/591099 fast/overflow/overflow-rtl-vertical.html [ Failure ] @@ -2364,13 +2374,9 @@ crbug.com/591099 fast/parser/001.html [ Failure ] crbug.com/591099 fast/parser/entities-in-html.html [ Failure ] crbug.com/591099 fast/parser/entities-in-xhtml.xhtml [ Failure ] -crbug.com/591099 fast/parser/nofoo-tags-inside-paragraph.html [ Failure Pass ] -crbug.com/591099 fast/reflections/opacity-reflection-transform.html [ Failure Pass ] crbug.com/591099 fast/replaced/absolute-position-percentage-height.html [ Failure ] crbug.com/591099 fast/replaced/border-radius-clip.html [ Failure ] crbug.com/591099 fast/replaced/computed-image-width-with-percent-height-and-fixed-ancestor-vertical-lr.html [ Failure ] -crbug.com/591099 fast/replaced/max-width-percent.html [ Failure Pass ] -crbug.com/591099 fast/replaced/percent-height-in-anonymous-block-in-table.html [ Failure Pass ] crbug.com/591099 fast/replaced/percent-height-in-anonymous-block.html [ Failure ] crbug.com/591099 fast/replaced/preferred-widths.html [ Failure ] crbug.com/591099 fast/replaced/replaced-element-with-percentage-height-anonymous-block-parent.html [ Failure ] @@ -2427,9 +2433,6 @@ crbug.com/714962 fast/scrolling/scrollbar-tickmarks-styled-after-onload.html [ Failure ] crbug.com/714962 fast/scrolling/scrollbar-tickmarks-styled.html [ Failure ] crbug.com/591099 fast/selectors/038.html [ Failure ] -crbug.com/591099 fast/selectors/040.html [ Failure Pass ] -crbug.com/591099 fast/selectors/041.html [ Failure Pass ] -crbug.com/591099 fast/selectors/042.html [ Failure Pass ] crbug.com/591099 fast/selectors/166.html [ Failure ] crbug.com/591099 fast/selectors/167.html [ Failure ] crbug.com/591099 fast/selectors/167a.html [ Failure ] @@ -2519,75 +2522,48 @@ crbug.com/591099 fast/spatial-navigation/snav-use-visual-viewport.html [ Failure ] crbug.com/591099 fast/sub-pixel/computedstylemargin.html [ Failure ] crbug.com/591099 fast/sub-pixel/inline-block-with-padding.html [ Failure ] -crbug.com/714962 fast/sub-pixel/size-of-span-with-different-positions.html [ Failure Pass ] crbug.com/591099 fast/sub-pixel/sub-pixel-border-2.html [ Failure ] crbug.com/591099 fast/table/018.html [ Failure ] crbug.com/591099 fast/table/032.html [ Failure ] crbug.com/714962 fast/table/035-vertical.html [ Failure ] crbug.com/714962 fast/table/040-vertical.html [ Failure ] crbug.com/714962 fast/table/040.html [ Failure ] -crbug.com/714962 fast/table/041.html [ Failure Pass ] crbug.com/714962 fast/table/absolute-table-at-bottom.html [ Failure ] crbug.com/714962 fast/table/auto-with-percent-height-vertical.html [ Failure ] -crbug.com/714962 fast/table/auto-with-percent-height.html [ Failure Pass ] -crbug.com/714962 fast/table/backgr_border-table-cell-collapsed-border.html [ Failure Pass ] crbug.com/714962 fast/table/backgr_border-table-cell.html [ Failure ] -crbug.com/714962 fast/table/backgr_border-table-collapsed-border.html [ Failure Pass ] -crbug.com/714962 fast/table/backgr_border-table-column-collapsed-border.html [ Failure Pass ] -crbug.com/714962 fast/table/backgr_border-table-column-group-collapsed-border.html [ Failure Pass ] crbug.com/714962 fast/table/backgr_border-table-column-group.html [ Failure ] crbug.com/714962 fast/table/backgr_border-table-column.html [ Failure ] -crbug.com/714962 fast/table/backgr_border-table-quirks-collapsed-border.html [ Failure Pass ] crbug.com/714962 fast/table/backgr_border-table-quirks.html [ Failure ] -crbug.com/714962 fast/table/backgr_border-table-row-collapsed-border.html [ Failure Pass ] -crbug.com/714962 fast/table/backgr_border-table-row-group-collapsed-border.html [ Failure Pass ] crbug.com/714962 fast/table/backgr_border-table-row-group.html [ Failure ] crbug.com/714962 fast/table/backgr_border-table-row.html [ Failure ] crbug.com/714962 fast/table/backgr_border-table.html [ Failure ] -crbug.com/714962 fast/table/backgr_layers-hide-collapsed-border.html [ Failure Pass ] crbug.com/714962 fast/table/backgr_layers-hide.html [ Failure ] crbug.com/591099 fast/table/backgr_layers-opacity-collapsed-border.html [ Failure ] crbug.com/591099 fast/table/backgr_layers-opacity.html [ Failure ] crbug.com/591099 fast/table/backgr_layers-show-collapsed-border.html [ Failure ] crbug.com/591099 fast/table/backgr_layers-show.html [ Failure ] -crbug.com/714962 fast/table/backgr_position-table-cell-collapsed-border.html [ Failure Pass ] crbug.com/714962 fast/table/backgr_position-table-cell.html [ Failure ] -crbug.com/714962 fast/table/backgr_position-table-collapsed-border.html [ Failure Pass ] -crbug.com/714962 fast/table/backgr_position-table-column-collapsed-border.html [ Failure Pass ] -crbug.com/714962 fast/table/backgr_position-table-column-group-collapsed-border.html [ Failure Pass ] crbug.com/714962 fast/table/backgr_position-table-column-group.html [ Failure ] crbug.com/714962 fast/table/backgr_position-table-column.html [ Failure ] -crbug.com/714962 fast/table/backgr_position-table-row-collapsed-border.html [ Failure Pass ] -crbug.com/714962 fast/table/backgr_position-table-row-group-collapsed-border.html [ Failure Pass ] crbug.com/714962 fast/table/backgr_position-table-row-group.html [ Failure ] crbug.com/714962 fast/table/backgr_position-table-row.html [ Failure ] crbug.com/714962 fast/table/backgr_position-table.html [ Failure ] -crbug.com/714962 fast/table/backgr_simple-table-cell-collapsed-border.html [ Failure Pass ] crbug.com/714962 fast/table/backgr_simple-table-cell.html [ Failure ] -crbug.com/714962 fast/table/backgr_simple-table-collapsed-border.html [ Failure Pass ] -crbug.com/714962 fast/table/backgr_simple-table-column-collapsed-border.html [ Failure Pass ] -crbug.com/714962 fast/table/backgr_simple-table-column-group-collapsed-border.html [ Failure Pass ] crbug.com/714962 fast/table/backgr_simple-table-column-group.html [ Failure ] crbug.com/714962 fast/table/backgr_simple-table-column.html [ Failure ] -crbug.com/714962 fast/table/backgr_simple-table-row-collapsed-border.html [ Failure Pass ] -crbug.com/714962 fast/table/backgr_simple-table-row-group-collapsed-border.html [ Failure Pass ] crbug.com/714962 fast/table/backgr_simple-table-row-group.html [ Failure ] crbug.com/714962 fast/table/backgr_simple-table-row.html [ Failure ] crbug.com/714962 fast/table/backgr_simple-table.html [ Failure ] crbug.com/591099 fast/table/border-collapsing/001-vertical.html [ Failure ] crbug.com/591099 fast/table/border-collapsing/003-vertical.html [ Failure ] crbug.com/591099 fast/table/border-collapsing/004-vertical.html [ Failure ] -crbug.com/591099 fast/table/border-collapsing/004.html [ Failure Pass ] crbug.com/591099 fast/table/border-collapsing/border-collapsing-head-foot-vertical.html [ Failure ] crbug.com/714962 fast/table/border-collapsing/border-collapsing-head-foot.html [ Failure ] crbug.com/591099 fast/table/border-collapsing/composited-cell-collapsed-border.html [ Failure ] -crbug.com/714962 fast/table/border-collapsing/rtl-border-collapsing-vertical.html [ Failure Pass ] -crbug.com/714962 fast/table/border-collapsing/rtl-border-collapsing.html [ Failure Pass ] crbug.com/591099 fast/table/column-in-inline.html [ Failure ] crbug.com/591099 fast/table/dynamic-descendant-percentage-height.html [ Failure ] crbug.com/591099 fast/table/empty-table-percent-height.html [ Failure ] crbug.com/591099 fast/table/fixed-table-layout/table-with-percent-width.html [ Failure ] -crbug.com/591099 fast/table/form-with-table-style.html [ Failure Pass ] crbug.com/591099 fast/table/height-percent-test-vertical.html [ Failure ] crbug.com/714962 fast/table/hittest-tablecell-bottom-edge.html [ Failure ] crbug.com/714962 fast/table/hittest-tablecell-right-edge.html [ Failure ] @@ -2602,14 +2578,11 @@ crbug.com/591099 fast/table/percent-height-overflow-auto-content-in-cell.html [ Failure Pass ] crbug.com/591099 fast/table/percent-height-overflow-scroll-content-in-cell.html [ Failure Pass ] crbug.com/591099 fast/table/percent-widths-stretch-vertical.html [ Failure ] -crbug.com/714962 fast/table/rtl-cell-display-none-assert.html [ Failure Pass ] crbug.com/714962 fast/table/split-table-section-before-anonymous-block-2.html [ Failure ] crbug.com/714962 fast/table/split-table-section-before-anonymous-block-3.html [ Failure ] crbug.com/714962 fast/table/split-table-section-before-anonymous-block-4.html [ Failure ] crbug.com/591099 fast/table/table-display-types-vertical.html [ Failure ] -crbug.com/714962 fast/table/text-field-baseline.html [ Failure Pass ] crbug.com/591099 fast/table/unbreakable-images-quirk.html [ Failure ] -crbug.com/591099 fast/table/unused-percent-heights.html [ Failure Pass ] crbug.com/591099 fast/table/vertical-align-baseline-readjust.html [ Failure ] crbug.com/591099 fast/text-autosizing/cluster-inline-block-or-table.html [ Failure ] crbug.com/591099 fast/text-autosizing/cluster-inline-grid-flex-box.html [ Failure ] @@ -2642,7 +2615,6 @@ crbug.com/591099 fast/text-autosizing/form-controls-autosizing-select-element.html [ Failure ] crbug.com/591099 fast/text-autosizing/form-controls-autosizing-textfield-input-elements.html [ Failure ] crbug.com/591099 fast/text-autosizing/form-controls-textfield-in-span.html [ Failure ] -crbug.com/591099 fast/text-autosizing/hackernews-comments.html [ Failure Pass ] crbug.com/591099 fast/text-autosizing/header-li-links-autosizing.html [ Failure ] crbug.com/591099 fast/text-autosizing/header-links-autosizing-different-fontsize.html [ Failure ] crbug.com/591099 fast/text-autosizing/header-links-autosizing.html [ Failure ] @@ -2673,7 +2645,6 @@ crbug.com/591099 fast/text-autosizing/wide-child.html [ Failure ] crbug.com/591099 fast/text-autosizing/wide-in-narrow-overflow-scroll.html [ Failure ] crbug.com/591099 fast/text/break-word-with-floats.html [ Failure ] -crbug.com/591099 fast/text/chromium-linux-fontconfig-renderstyle.html [ Failure Pass ] crbug.com/591099 fast/text/complex-text-opacity.html [ Failure ] crbug.com/591099 fast/text/container-align-with-inlines.html [ Failure ] crbug.com/591099 fast/text/decorations-transformed.html [ Failure ] @@ -2696,7 +2667,6 @@ crbug.com/714962 fast/text/get-client-rects-grapheme.html [ Failure ] crbug.com/714962 fast/text/glyph-reordering.html [ Failure ] crbug.com/591099 fast/text/hide-atomic-inlines-after-ellipsis.html [ Failure ] -crbug.com/714962 fast/text/international/bidi-layout-across-linebreak.html [ Failure Pass ] crbug.com/591099 fast/text/international/bidi-linebreak-002.html [ Failure ] crbug.com/591099 fast/text/international/bidi-linebreak-003.html [ Failure ] crbug.com/714962 fast/text/international/cjk-segmentation.html [ Failure ] @@ -2795,12 +2765,9 @@ crbug.com/591099 fast/writing-mode/text-combine-justify.html [ Failure ] crbug.com/591099 fast/writing-mode/text-combine-line-break.html [ Failure ] crbug.com/591099 fast/writing-mode/text-combine-various-fonts.html [ Failure ] -crbug.com/714962 fast/writing-mode/text-orientation-basic.html [ Failure Pass ] crbug.com/591099 fast/writing-mode/vertical-baseline-alignment.html [ Failure ] crbug.com/714962 fast/writing-mode/vertical-font-fallback.html [ Failure ] crbug.com/591099 fast/writing-mode/vertical-lr-replaced-selection.html [ Failure ] -crbug.com/591099 fast/xsl/xslt-entity.xml [ Failure Pass ] -crbug.com/591099 fast/xsl/xslt-extra-content-at-end.xml [ Failure Pass ] crbug.com/591099 fonts/monospace.html [ Failure ] crbug.com/591099 fonts/sans-serif.html [ Failure ] crbug.com/591099 fonts/serif.html [ Failure ] @@ -2897,7 +2864,6 @@ crbug.com/591099 fullscreen/full-screen-css.html [ Crash ] crbug.com/591099 fullscreen/full-screen-element-stack.html [ Crash ] crbug.com/591099 fullscreen/full-screen-iframe-not-allowed.html [ Failure ] -crbug.com/591099 fullscreen/full-screen-remove-ancestor-after.html [ Crash Pass ] crbug.com/591099 fullscreen/full-screen-ruleset-crash.html [ Crash Pass ] crbug.com/591099 fullscreen/full-screen-twice-newapi.html [ Crash ] crbug.com/591099 fullscreen/full-screen-with-css-reference-filter.html [ Crash ] @@ -2920,7 +2886,6 @@ crbug.com/591099 html/dialog/modal-dialog-in-table-column.html [ Failure ] crbug.com/591099 html/dialog/modal-dialog-scroll-height.html [ Failure ] crbug.com/591099 html/dialog/multiple-centered-dialogs.html [ Failure ] -crbug.com/591099 html/dialog/top-layer-containing-block.html [ Crash Pass ] crbug.com/591099 html/marquee/marquee-scroll.html [ Failure ] crbug.com/591099 html/marquee/marquee-scrollamount.html [ Failure ] crbug.com/591099 http/tests/css/css-image-valued-shape.html [ Failure ] @@ -2948,7 +2913,6 @@ crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside-scroll.js [ Failure ] crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside.js [ Failure ] crbug.com/714962 http/tests/devtools/elements/inspect-pseudo-element.js [ Timeout ] -crbug.com/591099 http/tests/devtools/elements/styles-2/paste-property.js [ Pass Timeout ] crbug.com/591099 http/tests/devtools/elements/styles-3/style-rule-from-imported-stylesheet.js [ Pass ] crbug.com/591099 http/tests/devtools/elements/styles-3/styles-change-node-while-editing.js [ Pass ] crbug.com/591099 http/tests/devtools/elements/styles-3/styles-disable-inherited.js [ Failure ] @@ -2981,9 +2945,7 @@ crbug.com/591099 http/tests/local/fileapi/select-dragged-file-input.html [ Skip ] crbug.com/591099 http/tests/misc/acid2.html [ Failure ] crbug.com/591099 http/tests/misc/acid3.html [ Crash ] -crbug.com/591099 http/tests/misc/object-embedding-svg-delayed-size-negotiation-2.htm [ Failure Pass ] crbug.com/591099 http/tests/misc/object-embedding-svg-delayed-size-negotiation.xhtml [ Failure ] -crbug.com/591099 http/tests/misc/slow-loading-mask.html [ Failure Pass ] crbug.com/591099 http/tests/origin_trials/sample-api-workers.html [ Pass ] crbug.com/591099 http/tests/permissions/test-api-surface.html [ Pass ] crbug.com/591099 http/tests/security/contentSecurityPolicy/directive-parsing-03.html [ Failure ] @@ -3047,7 +3009,7 @@ crbug.com/591099 inspector-protocol/css/css-set-style-text.js [ Timeout ] crbug.com/714962 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-viewport.js [ Failure ] crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js [ Timeout ] -crbug.com/591099 inspector-protocol/input/dispatchTouchEvent.js [ Pass Timeout ] +crbug.com/591099 inspector-protocol/input/dispatchTouchEvent.js [ Timeout ] crbug.com/714962 inspector-protocol/layers/paint-profiler.js [ Failure ] crbug.com/714962 inspector-protocol/layout-fonts/cjk-ideograph-fallback-by-lang.js [ Failure ] crbug.com/591099 inspector-protocol/layout-fonts/fallback-pua-last-resort.js [ Failure ] @@ -3070,10 +3032,6 @@ crbug.com/714962 intersection-observer/text-target.html [ Failure ] crbug.com/591099 media/audio-controls-rendering.html [ Failure ] crbug.com/591099 media/autoplay/document-user-activation.html [ Failure ] -crbug.com/591099 media/controls/volumechange-muted-attribute.html [ Failure Pass ] -crbug.com/591099 media/video-aspect-ratio.html [ Failure Pass ] -crbug.com/591099 media/video-colorspace-yuv420.html [ Failure Pass ] -crbug.com/591099 media/video-colorspace-yuv422.html [ Failure Pass ] crbug.com/591099 media/video-display-toggle.html [ Failure ] crbug.com/591099 media/video-persistence.html [ Crash ] crbug.com/591099 media/video-transformed.html [ Failure ] @@ -3103,7 +3061,6 @@ crbug.com/591099 paint/invalidation/clip/clip-with-layout-delta.html [ Failure ] crbug.com/591099 paint/invalidation/clip/clipped-relative.html [ Failure ] crbug.com/591099 paint/invalidation/clip/control-clip.html [ Failure ] -crbug.com/591099 paint/invalidation/clip/intermediate-layout-position-clip.html [ Failure ] crbug.com/591099 paint/invalidation/clip/outline-clip-change.html [ Failure ] crbug.com/591099 paint/invalidation/clip/repaint-tile-clipped.html [ Crash ] crbug.com/591099 paint/invalidation/clip/replaced-clipped-positioned-not-wrong-incremental-repainting.html [ Failure ] @@ -3112,8 +3069,6 @@ crbug.com/591099 paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/iframe-clip-removed.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/iframe-inside-squashed-layer.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/layer-repaint-rects.html [ Failure Pass ] -crbug.com/591099 paint/invalidation/compositing/layer-repaint.html [ Failure Pass ] crbug.com/591099 paint/invalidation/compositing/remove-squashed-layer-plus-move.html [ Failure ] crbug.com/714962 paint/invalidation/compositing/repaint-via-layout-offset.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/should-invoke-deferred-compositing.html [ Failure ] @@ -3315,7 +3270,6 @@ crbug.com/591099 paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure ] crbug.com/591099 paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure ] crbug.com/591099 paint/invalidation/svg/embedded-svg-size-changes-no-layout-triggers.html [ Failure ] -crbug.com/714962 paint/invalidation/svg/hit-test-with-br.xhtml [ Failure Pass ] crbug.com/591099 paint/invalidation/svg/nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure ] crbug.com/591099 paint/invalidation/svg/nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure ] crbug.com/591099 paint/invalidation/svg/object-sizing-no-width-height-change-content-box-size.xhtml [ Failure ] @@ -3356,6 +3310,7 @@ crbug.com/591099 paint/invalidation/table/caret-contenteditable-content-after.html [ Failure ] crbug.com/591099 paint/invalidation/table/collapsed-border-cell-resize.html [ Failure ] crbug.com/591099 paint/invalidation/table/collapsed-border-change-rowspan.html [ Failure ] +crbug.com/591099 paint/invalidation/table/collapsed-border-current-color.html [ Crash ] crbug.com/591099 paint/invalidation/table/composited-table-background-col-initial-empty.html [ Failure ] crbug.com/591099 paint/invalidation/table/composited-table-background-col-span-initial-empty.html [ Failure ] crbug.com/591099 paint/invalidation/table/composited-table-background-col-span.html [ Failure ] @@ -3419,7 +3374,6 @@ crbug.com/591099 paint/markers/first-letter.html [ Failure ] crbug.com/591099 paint/markers/inline-spelling-markers-hidpi-composited.html [ Failure ] crbug.com/591099 paint/markers/inline-spelling-markers-hidpi.html [ Failure ] -crbug.com/591099 paint/markers/inline_spelling_markers.html [ Failure Pass ] crbug.com/591099 paint/markers/marker-early-break-bug.html [ Failure ] crbug.com/591099 paint/overflow/background-mask-should-be-recorded-full.html [ Failure ] crbug.com/591099 paint/overflow/composited-scroll-vertical-rl.html [ Failure ] @@ -3519,11 +3473,8 @@ crbug.com/714962 svg/as-background-image/svg-as-background-body.html [ Failure ] crbug.com/591099 svg/as-border-image/svg-as-border-image-2.html [ Failure ] crbug.com/591099 svg/as-border-image/svg-as-border-image.html [ Failure ] -crbug.com/714962 svg/canvas/canvas-pattern-svg.html [ Failure Pass ] -crbug.com/591099 svg/custom/clone-element-with-animated-svg-properties.html [ Failure Pass ] crbug.com/591099 svg/custom/getscreenctm-in-scrollable-div-area-nested.xhtml [ Failure ] crbug.com/591099 svg/custom/getscreenctm-in-scrollable-div-area.xhtml [ Failure ] -crbug.com/591099 svg/custom/inline-svg-in-xhtml.xml [ Failure Pass ] crbug.com/591099 svg/custom/inline-svg-use-available-width-in-stf.html [ Failure ] crbug.com/591099 svg/custom/invisible-text-after-scrolling.xhtml [ Failure ] crbug.com/591099 svg/custom/junk-data.svg [ Failure ] @@ -3533,17 +3484,14 @@ crbug.com/591099 svg/custom/object-sizing-no-width-height.xhtml [ Failure ] crbug.com/591099 svg/custom/object-sizing.xhtml [ Failure ] crbug.com/591099 svg/custom/path-bad-data.svg [ Failure ] -crbug.com/591099 svg/custom/rootmost-svg-xy-attrs.xhtml [ Failure Pass ] crbug.com/591099 svg/custom/svg-fonts-in-html.html [ Failure ] crbug.com/591099 svg/custom/text-match-highlight.html [ Failure ] crbug.com/591099 svg/custom/transformed-text-pattern.html [ Failure ] crbug.com/591099 svg/custom/use-event-retargeting.html [ Failure ] crbug.com/591099 svg/custom/use-font-face-crash.svg [ Failure ] -crbug.com/714962 svg/dom/SVGStringList-basics.xhtml [ Failure Pass ] -crbug.com/591099 svg/dom/svgangle-units.html [ Pass Timeout ] +crbug.com/591099 svg/dom/svgangle-units.html [ Timeout ] crbug.com/591099 svg/filters/feTurbulence-bad-seeds.html [ Failure ] crbug.com/591099 svg/foreign-object-under-shadow-root-under-hidden.html [ Failure ] -crbug.com/591099 svg/foreignObject/svg-document-in-html-document.svg [ Failure Pass ] crbug.com/591099 svg/hixie/error/012.xml [ Failure ] crbug.com/591099 svg/hixie/error/013.xml [ Failure ] crbug.com/591099 svg/in-html/sizing/svg-inline.html [ Timeout ] @@ -3562,179 +3510,75 @@ crbug.com/591099 svg/transforms/text-with-pattern-inside-transformed-html.xhtml [ Failure ] crbug.com/591099 svg/transforms/transformed-text-fill-pattern.html [ Failure ] crbug.com/591099 svg/wicd/test-scalable-background-image1.xhtml [ Failure ] -crbug.com/591099 svg/zoom/page/zoom-hixie-mixed-009.xml [ Failure Pass ] -crbug.com/591099 svg/zoom/page/zoom-hixie-rendering-model-004.xhtml [ Failure Pass ] crbug.com/591099 svg/zoom/page/zoom-replaced-intrinsic-ratio-001.htm [ Failure ] -crbug.com/591099 svg/zoom/page/zoom-svg-through-object-with-percentage-size.xhtml [ Failure Pass ] -crbug.com/591099 svg/zoom/text/zoom-hixie-mixed-009.xml [ Failure Pass ] crbug.com/591099 tables/layering/paint-test-layering-1.html [ Failure ] crbug.com/591099 tables/layering/paint-test-layering-2.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug101674.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug106158-1.html [ Failure Pass ] -crbug.com/591099 tables/mozilla/bugs/bug106158-2.html [ Failure Pass ] -crbug.com/591099 tables/mozilla/bugs/bug109043.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug110566.html [ Failure ] -crbug.com/591099 tables/mozilla/bugs/bug113235-1.html [ Failure Pass ] crbug.com/714962 tables/mozilla/bugs/bug11384q.html [ Failure ] crbug.com/714962 tables/mozilla/bugs/bug11384s.html [ Failure ] -crbug.com/591099 tables/mozilla/bugs/bug1188.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug11944.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug12008.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug126742.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug1271.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug1302.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug131020-2.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug131020.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug131020_iframe.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug13118.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug1318.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug13196.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug133948.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug137388-1.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug137388-2.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug137388-3.html [ Failure ] crbug.com/714962 tables/mozilla/bugs/bug139524-2.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug14159-1.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug1430.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug149275-1.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug149275-2.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug16252.html [ Failure Pass ] crbug.com/714962 tables/mozilla/bugs/bug17130-1.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug18359.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug18440.html [ Failure ] -crbug.com/591099 tables/mozilla/bugs/bug18664.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug18955.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug19599.html [ Failure Pass ] -crbug.com/591099 tables/mozilla/bugs/bug20579.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug219693-2.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug2267.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug23235.html [ Failure ] -crbug.com/591099 tables/mozilla/bugs/bug2479-1.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug2479-3.html [ Failure ] crbug.com/714962 tables/mozilla/bugs/bug2479-4.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug2509.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug26553.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug27038-1.html [ Failure ] -crbug.com/591099 tables/mozilla/bugs/bug27038-2.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug2757.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug2886-2.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug2947.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug2962.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug2973.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug2981-1.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug2981-2.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug2997.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug30692.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug3191.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug32205-3.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug3454.html [ Failure Pass ] crbug.com/714962 tables/mozilla/bugs/bug38916.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug3977.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug43039.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug4427.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug44523.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug4501.html [ Failure Pass ] crbug.com/714962 tables/mozilla/bugs/bug4576.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug46268-1.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug46268-2.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug46268-5.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug46268.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug46368-1.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug46368-2.html [ Failure Pass ] crbug.com/714962 tables/mozilla/bugs/bug46480-1.html [ Failure ] crbug.com/714962 tables/mozilla/bugs/bug46480-2.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug46623-1.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug46623-2.html [ Failure Pass ] crbug.com/714962 tables/mozilla/bugs/bug46924.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug48028-1.html [ Failure Pass ] crbug.com/714962 tables/mozilla/bugs/bug4803.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug4849-2.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug48827.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug50695-2.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug5188.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug53690-2.html [ Failure ] -crbug.com/591099 tables/mozilla/bugs/bug5538.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug55694.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug57828-2.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug57828.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug5798.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug58402-1.html [ Failure ] -crbug.com/591099 tables/mozilla/bugs/bug59354.html [ Failure Pass ] -crbug.com/591099 tables/mozilla/bugs/bug6304.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug641-2.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug650.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug69382-2.html [ Failure Pass ] -crbug.com/591099 tables/mozilla/bugs/bug7112-1.html [ Failure Pass ] -crbug.com/591099 tables/mozilla/bugs/bug7112-2.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug727.html [ Failure Pass ] -crbug.com/591099 tables/mozilla/bugs/bug7342.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug78162.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug80762-1.html [ Failure Pass ] crbug.com/714962 tables/mozilla/bugs/bug82946-1.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug82946-2.html [ Failure Pass ] -crbug.com/591099 tables/mozilla/bugs/bug8381.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug88035-1.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug88035-2.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug88524.html [ Failure ] crbug.com/714962 tables/mozilla/bugs/bug9123-1.html [ Failure ] -crbug.com/714962 tables/mozilla/bugs/bug93363.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/bugs/bug96334.html [ Failure Pass ] crbug.com/591099 tables/mozilla/bugs/bug98196.html [ Failure ] -crbug.com/591099 tables/mozilla/collapsing_borders/bug41262-3.html [ Failure Pass ] crbug.com/591099 tables/mozilla/core/bloomberg.html [ Failure ] crbug.com/591099 tables/mozilla/core/table_heights.html [ Failure ] -crbug.com/714962 tables/mozilla/marvin/col_span.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/colgroup_span.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/colgroup_width_pct.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/colgroup_width_px.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_cellpadding.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_cellpadding_pct.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_cellspacing.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_class.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_style.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_td_colspan.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_td_height.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_td_rowspan.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_td_width.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_th_colspan.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_th_height.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_th_rowspan.html [ Failure Pass ] -crbug.com/591099 tables/mozilla/marvin/tables_th_width.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_width_percent.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tables_width_px.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/tbody_char.html [ Failure Pass ] -crbug.com/591099 tables/mozilla/marvin/tfoot_char.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/thead_char.html [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/x_col_width_pct.xml [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/x_col_width_px.xml [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/x_col_width_rel.xml [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/x_colgroup_width_pct.xml [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/x_colgroup_width_rel.xml [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/x_table.xml [ Failure Pass ] -crbug.com/714962 tables/mozilla/marvin/x_table_style.xml [ Failure Pass ] -crbug.com/714962 tables/mozilla/other/cellspacing.html [ Failure Pass ] crbug.com/714962 tables/mozilla/other/test3.html [ Failure ] crbug.com/714962 tables/mozilla/other/test6.html [ Failure ] crbug.com/591099 tables/mozilla/other/wa_table_thtd_rowspan.html [ Failure ] crbug.com/591099 tables/mozilla_expected_failures/bugs/bug1010.html [ Failure ] crbug.com/714962 tables/mozilla_expected_failures/bugs/bug1055-2.html [ Failure ] crbug.com/714962 tables/mozilla_expected_failures/bugs/bug1128.html [ Failure ] -crbug.com/714962 tables/mozilla_expected_failures/bugs/bug14007-1.html [ Failure Pass ] -crbug.com/714962 tables/mozilla_expected_failures/bugs/bug21518.html [ Failure Pass ] -crbug.com/714962 tables/mozilla_expected_failures/bugs/bug22122.html [ Failure Pass ] -crbug.com/714962 tables/mozilla_expected_failures/bugs/bug2479-5.html [ Failure Pass ] -crbug.com/714962 tables/mozilla_expected_failures/bugs/bug25707.html [ Failure Pass ] crbug.com/714962 tables/mozilla_expected_failures/bugs/bug32205-4.html [ Failure ] -crbug.com/714962 tables/mozilla_expected_failures/bugs/bug42043.html [ Failure Pass ] -crbug.com/714962 tables/mozilla_expected_failures/bugs/bug4294.html [ Failure Pass ] -crbug.com/714962 tables/mozilla_expected_failures/bugs/bug51000.html [ Failure Pass ] -crbug.com/714962 tables/mozilla_expected_failures/bugs/bug56024.html [ Failure Pass ] crbug.com/591099 tables/mozilla_expected_failures/bugs/bug7113.html [ Failure ] -crbug.com/714962 tables/mozilla_expected_failures/bugs/bug72393.html [ Failure Pass ] -crbug.com/714962 tables/mozilla_expected_failures/bugs/bug80762-2.html [ Failure Pass ] crbug.com/591099 tables/mozilla_expected_failures/bugs/bug85016.html [ Failure ] crbug.com/714962 tables/mozilla_expected_failures/bugs/bug91057.html [ Failure ] -crbug.com/714962 tables/mozilla_expected_failures/core/standards1.html [ Failure Pass ] crbug.com/591099 tables/mozilla_expected_failures/marvin/backgr_fixed-bg.html [ Failure ] crbug.com/591099 tables/mozilla_expected_failures/marvin/table_overflow_caption.html [ Failure ] crbug.com/591099 tables/mozilla_expected_failures/marvin/table_overflow_caption_bottom.html [ Failure ] @@ -3743,23 +3587,18 @@ crbug.com/591099 tables/mozilla_expected_failures/marvin/table_overflow_caption_left.html [ Failure ] crbug.com/591099 tables/mozilla_expected_failures/marvin/table_overflow_caption_right.html [ Failure ] crbug.com/591099 tables/mozilla_expected_failures/marvin/table_overflow_caption_top.html [ Failure ] -crbug.com/714962 tables/mozilla_expected_failures/marvin/tables_cellspacing_pct.html [ Failure Pass ] -crbug.com/714962 tables/mozilla_expected_failures/marvin/x_colgroup_width_px.xml [ Failure Pass ] crbug.com/714962 touchadjustment/context-menu-select-text.html [ Failure ] crbug.com/714962 touchadjustment/context-menu-text-subtargets.html [ Failure ] crbug.com/714962 touchadjustment/touch-links-longpress.html [ Failure ] crbug.com/591099 transforms/2d/compound-transforms-vs-containers.html [ Failure ] crbug.com/591099 transforms/2d/hindi-rotated.html [ Failure ] crbug.com/591099 transforms/2d/transform-2d.html [ Timeout ] -crbug.com/591099 transforms/2d/transform-fixed-container.html [ Failure Pass ] crbug.com/591099 transforms/3d/general/perspective-non-layer.html [ Failure ] crbug.com/591099 transforms/3d/hit-testing/backface-hit-test.html [ Failure ] crbug.com/591099 transforms/3d/hit-testing/backface-no-transform-hit-test.html [ Failure ] crbug.com/714962 transforms/inline-in-transformed-multicol.html [ Failure ] crbug.com/714962 transforms/selection-bounds-in-transformed-view.html [ Failure ] crbug.com/591099 transforms/shadows.html [ Failure ] -crbug.com/591099 transforms/transform-positioned-ancestor.html [ Failure Pass ] -crbug.com/591099 transforms/transforms-with-zoom.html [ Failure Pass ] crbug.com/591099 virtual/android/ [ Skip ] crbug.com/591099 virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-linear-rgb.html [ Pass ] crbug.com/591099 virtual/color_space/fast/canvas/color-space/canvas-createImageBitmap-p3.html [ Pass ] @@ -3797,10 +3636,6 @@ crbug.com/714962 virtual/gpu/fast/canvas/canvas-css-clip-path.html [ Failure ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-drawImage-video-imageSmoothingEnabled.html [ Pass ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-imageSmoothingQuality.html [ Pass ] -crbug.com/714962 virtual/gpu/fast/canvas/canvas-textMetrics-width.html [ Failure Pass ] -crbug.com/714962 virtual/gpu/fast/canvas/image-object-in-canvas.html [ Failure Pass ] -crbug.com/591099 virtual/gpu/fast/canvas/patternfill-repeat.html [ Failure Pass ] -crbug.com/714962 virtual/gpu/fast/canvas/setWidthResetAfterForcedRender.html [ Failure Pass ] crbug.com/591099 virtual/incremental-shadow-dom/external/wpt/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html [ Failure ] crbug.com/591099 virtual/incremental-shadow-dom/external/wpt/shadow-dom/untriaged/html-elements-in-shadow-trees/html-forms/test-002.html [ Pass ] crbug.com/591099 virtual/incremental-shadow-dom/external/wpt/shadow-dom/untriaged/shadow-trees/reprojection/reprojection-001.html [ Pass ] @@ -3870,11 +3705,8 @@ crbug.com/591099 virtual/prefer_compositing_to_lcd_text/ [ Skip ] crbug.com/714962 virtual/pwa-full-code-cache/http/tests/devtools/service-workers/service-workers-view.js [ Failure ] crbug.com/591099 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Pass ] -crbug.com/591099 virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance.html [ Failure Pass ] crbug.com/591099 virtual/scalefactor150/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure ] -crbug.com/714962 virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance.html [ Failure Pass ] crbug.com/591099 virtual/scalefactor200/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure ] -crbug.com/714962 virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-appearance.html [ Failure Pass ] crbug.com/591099 virtual/scalefactor200withzoom/fast/hidpi/static/popup-menu-with-scrollbar-appearance.html [ Failure ] crbug.com/591099 virtual/scroll_customization/ [ Skip ] crbug.com/591099 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-animation.html [ Pass ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 2708dbb..7655a7b 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -158,6 +158,7 @@ crbug.com/711704 external/wpt/css/CSS2/floats/floats-rule7-outside-right-001.xht [ Failure ] crbug.com/711704 external/wpt/css/CSS2/floats/floats-wrap-bfc-006.xht [ Failure ] +crbug.com/711709 external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins-no-clearance.html [ Failure ] crbug.com/711709 external/wpt/css/CSS2/floats-clear/floating-replaced-height-008.xht [ Skip ] crbug.com/711709 external/wpt/css/CSS2/floats-clear/floats-108.xht [ Skip ] crbug.com/711709 external/wpt/css/CSS2/floats-clear/floats-109.xht [ Skip ] @@ -843,6 +844,8 @@ crbug.com/813098 external/wpt/editing/run/removeformat.html [ Timeout Pass ] +crbug.com/821455 [ Linux ] editing/pasteboard/drag-files-to-editable-element.html [ Failure Pass ] + crbug.com/688613 external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.https.html [ Skip ] crbug.com/688613 virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-audio-is-silence.https.html [ Skip ] @@ -1304,19 +1307,16 @@ crbug.com/582836 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-declaration-17.html [ Failure Pass ] crbug.com/582836 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-declaration-18.html [ Failure Pass ] crbug.com/582836 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-external-font-face-01.html [ Pass Failure ] -crbug.com/582836 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-font-face-01.html [ Failure ] -crbug.com/582836 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/variables/variable-font-face-02.html [ Failure ] -crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-break-inside-001a.html [ Failure ] -crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-005a.html [ Failure Pass ] -crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-006.html [ Failure ] -crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-001.html [ Failure Pass ] -crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-002.html [ Failure Pass ] -crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-003.html [ Failure Pass ] -crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-004.html [ Failure Pass ] -crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-005.html [ Failure Pass ] -crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-006a.html [ Failure Pass ] -crbug.com/736319 [ Linux Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-007.html [ Failure Pass ] +crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-break-inside-001a.html [ Failure ] +crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-001.html [ Failure ] +crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-002.html [ Failure ] +crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-003.html [ Failure ] +crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-004.html [ Failure ] +crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-005.html [ Failure ] +crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-005a.html [ Failure ] +crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-006.html [ Failure ] +crbug.com/736319 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/writing-modes-3/text-combine-upright-compression-006a.html [ Failure ] crbug.com/752449 [ Mac10.12 Mac10.13 Retina ] external/wpt/css/css-fonts/matching/fixed-stretch-style-over-weight.html [ Failure ] crbug.com/752449 [ Mac10.12 Retina ] external/wpt/css/css-fonts/matching/stretch-distance-over-weight-distance.html [ Failure ] @@ -1432,9 +1432,6 @@ crbug.com/v8/7486 http/tests/devtools/startup/console/console-format-startup-bigint.js [ Skip ] crbug.com/v8/7486 http/tests/devtools/console/console-format-bigint.js [ Skip ] -# Temporarily disable test until we land change to v8::ScriptCompiler::CompileFunctionInContext. -crbug.com/v8/7172 inspector-protocol/debugger/step-into-inline-event-handler.js [ NeedsManualRebaseline ] - crbug.com/564109 [ Win ] http/tests/webfont/font-display-intervention.html [ Pass Failure Timeout ] crbug.com/399951 http/tests/mime/javascript-mimetype-usecounters.html [ Pass Failure ] @@ -1671,6 +1668,7 @@ crbug.com/805463 external/wpt/acid/acid3/numbered-tests.html [ Skip ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/payment-request/payment-request-canmakepayment-method-manual.https.html [ Skip ] crbug.com/626703 [ Mac10.11 ] external/wpt/payment-handler/can-make-payment-event-constructor.https.worker.html [ Timeout ] crbug.com/626703 [ Linux Win ] external/wpt/css/css-text/letter-spacing/letter-spacing-control-chars-001.html [ Failure ] crbug.com/626703 [ Linux Mac10.10 Mac10.12 Mac10.13 Retina Win ] external/wpt/payment-handler/can-make-payment-event-constructor.https.worker.html [ Timeout ] @@ -1716,7 +1714,7 @@ crbug.com/626703 external/wpt/css/css-text/white-space/pre-wrap-002.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/white-space/white-space-collapsing-preserve-breaks-001.xht [ Failure ] crbug.com/626703 [ Linux Mac10.12 Retina Win ] external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Failure ] -crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-upperlower-028.html [ Failure ] +crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-upperlower-006.html [ Failure ] crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/white-space/pre-wrap-006.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-capitalize-028.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/word-break/word-break-keep-all-004.xht [ Skip ] @@ -1724,14 +1722,12 @@ crbug.com/626703 [ Win10 ] external/wpt/css/css-text/text-align/text-align-justify-004.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justifyall-005.html [ Failure ] crbug.com/626703 [ Win ] external/wpt/css/css-text/word-break/word-break-normal-km-000.html [ Failure ] -crbug.com/626703 [ Linux Win ] external/wpt/css/css-text/text-transform/text-transform-upperlower-016.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/white-space/pre-wrap-010.html [ Failure ] crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/text-align/text-align-end-016.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-fullwidth-001.xht [ Failure ] crbug.com/626703 external/wpt/css/css-text/word-break/word-break-keep-all-003.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/word-break/word-break-normal-my-000.html [ Failure ] crbug.com/626703 [ Win7 ] external/wpt/css/css-text/text-justify/text-justify-001.html [ Failure ] -crbug.com/626703 external/wpt/css/css-text/text-transform/text-transform-upperlower-029.html [ Failure ] crbug.com/626703 [ Win Mac ] external/wpt/css/css-text/text-align/text-align-start-004.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/text-align/text-align-justifyall-006.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/hanging-punctuation/hanging-punctuation-allow-end-001.xht [ Skip ] @@ -1943,7 +1939,6 @@ crbug.com/626703 external/wpt/css/css-fonts/font-features-across-space-1.html [ Failure ] crbug.com/626703 external/wpt/css/css-fonts/font-features-across-space-3.html [ Failure ] crbug.com/626703 external/wpt/css/css-fonts/font-kerning-03.html [ Failure ] -crbug.com/626703 external/wpt/css/css-fonts/font-variant-alternates-01.html [ Failure ] crbug.com/626703 external/wpt/css/css-fonts/font-variant-alternates-02.html [ Failure ] crbug.com/626703 external/wpt/css/css-fonts/font-variant-alternates-03.html [ Failure ] crbug.com/626703 external/wpt/css/css-fonts/font-variant-alternates-04.html [ Failure ] @@ -3368,7 +3363,7 @@ crbug.com/811977 virtual/new-remote-playback-pipeline/media/controls/picture-in-picture-interstitial.html [ Skip ] # Sheriff 2018-02-26 -crbug.com/816475 [ Win7 ] external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Failure Pass ] +crbug.com/816475 [ Win7 Linux ] external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Failure Pass ] crbug.com/816914 [ Mac ] fast/canvas/canvas-drawImage-live-video.html [ Failure Pass ] crbug.com/816766 [ Mac ] fast/dom/Window/window-focus-self.html [ Failure Pass ] crbug.com/817167 http/tests/devtools/oopif/oopif-cookies-refresh.js [ Failure Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/accessibility/aom-click-action.html b/third_party/WebKit/LayoutTests/accessibility/aom-click-action.html index fb33992..a1dc7fc 100644 --- a/third_party/WebKit/LayoutTests/accessibility/aom-click-action.html +++ b/third_party/WebKit/LayoutTests/accessibility/aom-click-action.html
@@ -228,3 +228,30 @@ }); }, "AOM event bubbling respects aria-owns over DOM parent chain"); </script> + +<p id="container7" aria-label="Container7"></p> + +<script> +async_test(function(t) { + enableAccessibilityEventsPermission().then(function() { + var container7 = document.getElementById("container7"); + var axContainer7 = accessibilityController.accessibleElementById( + "container7"); + + var virtualNode = new AccessibleNode(); + virtualNode.role = "button"; + virtualNode.label = "Button7"; + container7.accessibleNode.appendChild(virtualNode); + var axVirtualNode = axContainer7.childAtIndex(0); + + var success = false; + virtualNode.onaccessibleclick = function() { + success = true; + }; + axVirtualNode.press(); + + assert_true(success); + t.done(); + }); +}, "AccessibleNode.onaccessibleclick on virtual node"); +</script>
diff --git a/third_party/WebKit/LayoutTests/accessibility/aom-virtual.html b/third_party/WebKit/LayoutTests/accessibility/aom-virtual.html index 4b8baa02..d6dca9ce 100644 --- a/third_party/WebKit/LayoutTests/accessibility/aom-virtual.html +++ b/third_party/WebKit/LayoutTests/accessibility/aom-virtual.html
@@ -74,3 +74,26 @@ assert_equals(axListItem2.role, "AXRole: AXListItem"); }, "Create a virtual list using AccessibleNodes"); </script> + +<script> +test(function(t) { + var container = document.getElementById("container2"); + + var list1 = new AccessibleNode(); + list1.role = "list"; + container.accessibleNode.appendChild(list1); + + var list2 = new AccessibleNode(); + list2.role = "list"; + container.accessibleNode.appendChild(list2); + + var item = new AccessibleNode(); + item.role = "listitem"; + list1.appendChild(item); + + // TODO: support reparenting and then fix this test. + assert_throws('NotSupportedError', function() { + list2.appendChild(item); + }); +}, "Reparenting is not supported yet"); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 5badc09..3f612a36 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -4681,6 +4681,12 @@ {} ] ], + "payment-request/payment-request-canmakepayment-method-manual.https.html": [ + [ + "/payment-request/payment-request-canmakepayment-method-manual.https.html", + {} + ] + ], "payment-request/payment-response/complete-method-manual.https.html": [ [ "/payment-request/payment-response/complete-method-manual.https.html", @@ -98409,26 +98415,6 @@ {} ] ], - "beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt": [ - [ - {} - ] - ], - "beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt": [ - [ - {} - ] - ], - "beacon/headers/header-referrer-strict-origin.https-expected.txt": [ - [ - {} - ] - ], - "beacon/headers/header-referrer-unsafe-url.https-expected.txt": [ - [ - {} - ] - ], "beacon/headers/header-referrer.js": [ [ {} @@ -98654,6 +98640,21 @@ {} ] ], + "client-hints/OWNERS": [ + [ + {} + ] + ], + "client-hints/accept_ch.https.html.headers": [ + [ + {} + ] + ], + "client-hints/echo_device_memory_header_received.py": [ + [ + {} + ] + ], "clipboard-apis/OWNERS": [ [ {} @@ -174795,6 +174796,12 @@ {} ] ], + "client-hints/accept_ch.https.html": [ + [ + "/client-hints/accept_ch.https.html", + {} + ] + ], "clipboard-apis/async-interfaces.https.html": [ [ "/clipboard-apis/async-interfaces.https.html", @@ -183531,6 +183538,12 @@ {} ] ], + "css/css-typed-om/the-stylepropertymap/properties/scroll-padding.html": [ + [ + "/css/css-typed-om/the-stylepropertymap/properties/scroll-padding.html", + {} + ] + ], "css/css-typed-om/the-stylepropertymap/properties/shape-outside.html": [ [ "/css/css-typed-om/the-stylepropertymap/properties/shape-outside.html", @@ -215611,12 +215624,6 @@ {} ] ], - "payment-request/payment-request-canmakepayment-method.https.html": [ - [ - "/payment-request/payment-request-canmakepayment-method.https.html", - {} - ] - ], "payment-request/payment-request-constructor-crash.https.html": [ [ "/payment-request/payment-request-constructor-crash.https.html", @@ -250184,10 +250191,6 @@ "aee7b4c817f064e871d10cc80da8d25759c16158", "testharness" ], - "beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt": [ - "4ea0030e9c86e1f28d1c1f52208907bc11c0acc3", - "support" - ], "beacon/headers/header-referrer-no-referrer-when-downgrade.https.html": [ "273c7d0110d5efc9fac0029cd257256894d3eb4b", "testharness" @@ -250208,26 +250211,14 @@ "9701f2f0a83c6eeefe781d7de2c0cdbcff38b58e", "testharness" ], - "beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt": [ - "4ea0030e9c86e1f28d1c1f52208907bc11c0acc3", - "support" - ], "beacon/headers/header-referrer-strict-origin-when-cross-origin.https.html": [ "295ef746c475fca0ae8b492375a48948b4ea19c3", "testharness" ], - "beacon/headers/header-referrer-strict-origin.https-expected.txt": [ - "4ea0030e9c86e1f28d1c1f52208907bc11c0acc3", - "support" - ], "beacon/headers/header-referrer-strict-origin.https.html": [ "295ef746c475fca0ae8b492375a48948b4ea19c3", "testharness" ], - "beacon/headers/header-referrer-unsafe-url.https-expected.txt": [ - "cd3cfb43cf8a6c7e1fafaa4262f0fd7df7633872", - "support" - ], "beacon/headers/header-referrer-unsafe-url.https.html": [ "a7b6e697be165124ed5d6846335c8d3a38ee98f5", "testharness" @@ -251052,6 +251043,22 @@ "10f5f9d409ef513edb129e0e8522aa5f74d51ce8", "support" ], + "client-hints/OWNERS": [ + "56ef0ac9f9d3c2fcd69f16c409599402de8057f0", + "support" + ], + "client-hints/accept_ch.https.html": [ + "b54ae9b17399e0fe4472fedbf1badd67d28e68f3", + "testharness" + ], + "client-hints/accept_ch.https.html.headers": [ + "bf59baf9a030d117964df414efc11ddb07e7a7fa", + "support" + ], + "client-hints/echo_device_memory_header_received.py": [ + "defa16c455bebc2589c058d0d888326d667e317a", + "support" + ], "clipboard-apis/OWNERS": [ "29571a481e6d9fbbef55c7e0731280f08af5ac93", "support" @@ -303356,6 +303363,10 @@ "68a2611eaf9eecb7393c2b0db0f4378ebe285f22", "testharness" ], + "css/css-typed-om/the-stylepropertymap/properties/scroll-padding.html": [ + "d37d336e4695e5055706a7822572b81b943fdbd4", + "testharness" + ], "css/css-typed-om/the-stylepropertymap/properties/shape-outside-expected.txt": [ "fda10e01b3af2298d545ebcfb5e3c77ed91c8932", "support" @@ -324317,7 +324328,7 @@ "testharness" ], "fetch/api/redirect/redirect-location.js": [ - "3b48bf04659cc82462c3f33db47fd2f44f63c0c3", + "c8795b2a372e365e1b6e052d8a3309f3bfb2c143", "support" ], "fetch/api/redirect/redirect-method-worker.html": [ @@ -345901,7 +345912,7 @@ "support" ], "interfaces/magnetometer.idl": [ - "78fdc6ec345a5f05e86cb104cb025689638bbe17", + "ffac480912edba82886fef6d5368092d237a0c7f", "support" ], "interfaces/mediacapture-main.idl": [ @@ -345909,7 +345920,7 @@ "support" ], "interfaces/orientation-sensor.idl": [ - "d75a765c9456c21ed2733fa89a20f3e2d0eb2131", + "1f0698a8611726b1ba724a5d7a0961e836c7b07e", "support" ], "interfaces/payment-handler.idl": [ @@ -355440,14 +355451,14 @@ "30c62af4a05a4d83cbbd1e82d0df62bae9a85e96", "testharness" ], + "payment-request/payment-request-canmakepayment-method-manual.https.html": [ + "40e5bf0445eedb6bb78bd61fa4a468652462a14d", + "manual" + ], "payment-request/payment-request-canmakepayment-method.https-expected.txt": [ "edf4b9aedbdc74041e2aa49d77eaa177954f0f80", "support" ], - "payment-request/payment-request-canmakepayment-method.https.html": [ - "0d863558b996df81a36207201bbf8c649688845d", - "testharness" - ], "payment-request/payment-request-constructor-crash.https.html": [ "383d1c3f9505ee63d504bee87e13efa90ba49f3d", "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt deleted file mode 100644 index 27ce7532..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-no-referrer-when-downgrade.https-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -PASS Test referer header https://web-platform.test:8444/beacon/resources/ -FAIL Test referer header http://web-platform.test:8001/beacon/resources/ assert_true: SendBeacon Succeeded expected true got false -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt deleted file mode 100644 index 27ce7532..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-strict-origin-when-cross-origin.https-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -PASS Test referer header https://web-platform.test:8444/beacon/resources/ -FAIL Test referer header http://web-platform.test:8001/beacon/resources/ assert_true: SendBeacon Succeeded expected true got false -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-strict-origin.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-strict-origin.https-expected.txt deleted file mode 100644 index 27ce7532..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-strict-origin.https-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -PASS Test referer header https://web-platform.test:8444/beacon/resources/ -FAIL Test referer header http://web-platform.test:8001/beacon/resources/ assert_true: SendBeacon Succeeded expected true got false -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-unsafe-url.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-unsafe-url.https-expected.txt deleted file mode 100644 index 6c07551..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/beacon/headers/header-referrer-unsafe-url.https-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL Test referer header http://web-platform.test:8001/beacon/resources/ assert_true: SendBeacon Succeeded expected true got false -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-child-with-margins.html b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-child-with-margins.html new file mode 100644 index 0000000..f65f314 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-child-with-margins.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<title>Child of block with clear</title> +<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#flow-control" title="9.5.2 Controlling flow next to floats: the 'clear' property"> +<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html"> +<p>Test passes if there is a filled green square.</p> +<div style="position:relative; top:-20px;"> + <div style="float:left; margin-top:20px; width:50px; height:50px; background:green;"></div> + <div style="padding-top:1px;"> + <div style="margin-top:19px; width:100px; background:green;"> + <div style="clear:left; margin-top:25px; width:100px; height:50px; background:green;"></div> + </div> + </div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-and-child.html b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-and-child.html new file mode 100644 index 0000000..d7dc26f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-and-child.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<title>Child of block with clear</title> +<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#flow-control" title="9.5.2 Controlling flow next to floats: the 'clear' property"> +<link rel="match" href="../../reference/ref-filled-green-200px-square.html"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div id="container" style="overflow:hidden; width:200px; height:200px; background:red;"> + <div style="float:left; width:10px; height:50px;"></div> + <div style="float:right; width:10px; height:100px;"></div> + <div style="clear:right;"> + <div style="clear:left; height:200px; background:green;"></div> + </div> + <div style="height:10000px;"></div> +</div> +<script> + document.getElementById("container").scrollTop = 100; +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins-no-clearance.html b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins-no-clearance.html new file mode 100644 index 0000000..29ecc78f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins-no-clearance.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<title>Child of block with clear</title> +<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#flow-control" title="9.5.2 Controlling flow next to floats: the 'clear' property"> +<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html"> +<p>Test passes if there is a filled green square.</p> +<div style="position:relative; z-index:-1; top:-50px; width:100px; background:green;"> + <div style="float:left; width:100px; height:50px; background:white;"></div> + <div style="clear:left; margin-top:25px;"> + <div style="height:50px; margin-top:150px; background:white;"></div> + </div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins.html b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins.html new file mode 100644 index 0000000..9b331d5e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent-with-margins.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<title>Child of block with clear</title> +<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#flow-control" title="9.5.2 Controlling flow next to floats: the 'clear' property"> +<link rel="match" href="../../reference/ref-filled-green-200px-square.html"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="width:200px; height:200px; background:red;"> + <div style="float:left; width:200px; height:100px; background:green;"></div> + <div style="clear:left; margin-top:100px;"> + <div style="height:100px; margin-top:-1000px; background:green;"></div> + </div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent.html b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent.html new file mode 100644 index 0000000..755cd78 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/CSS2/floats-clear/clear-on-parent.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<title>Child of block with clear</title> +<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#flow-control" title="9.5.2 Controlling flow next to floats: the 'clear' property"> +<link rel="match" href="../../reference/ref-filled-green-200px-square.html"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="width:200px; height:200px; background:red;"> + <div style="float:left; width:200px; height:100px; background:green;"></div> + <div style="clear:left;"> + <div style="height:100px; background:green;"></div> + </div> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html new file mode 100644 index 0000000..defe06f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html
@@ -0,0 +1,84 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src=/feature-policy/resources/featurepolicy.js></script> + <!-- Feature-Policy: fullscreen *; --> + <script> + 'use strict'; + var same_origin = 'https://{{domains[]}}:{{ports[https][0]}}'; + var cross_origin = 'https://{{domains[www]}}:{{ports[https][0]}}'; + var same_origin_src = '/feature-policy/resources/feature-policy-allowedfeatures.html'; + var cross_origin_src = cross_origin + same_origin_src; + var policies = [ + {allow: "*", sameOriginTestExpect: true, crossOriginTestExpect: true}, + {allow: "'self'", sameOriginTestExpect: true, crossOriginTestExpect: false}, + {allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false}, + {allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: true, crossOriginTestExpect: true}]; + var pipe_front = '?pipe=sub|header(Feature-Policy,fullscreen '; + var pipe_end = ';)'; + var header_policies = ["*", "'self'", "'none'"]; + + // Test that frame.policy inherits from parent's header policy when allow + // attribute is not specified. + test(function() { + test_frame_policy('fullscreen', same_origin_src, true); + }, 'Test frame policy on same origin iframe inherit from header policy.'); + test(function() { + test_frame_policy('fullscreen', cross_origin_src, true); + }, 'Test frame policy on cross origin iframe inherit from header policy.'); + + // Test frame policy with allow attribute set to be one of the policies above. + for (var i = 0; i < policies.length; i++) { + test(function() { + test_frame_policy( + 'fullscreen', same_origin_src, policies[i].sameOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + '".'); + test(function() { + test_frame_policy( + 'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + '".'); + } + + // Test that the header policy of the iframe document does not change the + // frame policy. + for (var i = 0; i < policies.length; i++) { + for (var j = 0; j < header_policies.length; j++) { + test(function() { + test_frame_policy( + 'fullscreen', + same_origin_src + pipe_front + header_policies[j] + pipe_end, + policies[i].sameOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + + '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".'); + test(function() { + test_frame_policy( + 'fullscreen', + cross_origin_src + pipe_front + header_policies[j] + pipe_end, + policies[i].crossOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + + '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".'); + } + } + + // Test that the allow attribute overrides allowfullscreen. + for (var i = 0; i < policies.length; i++) { + test(function() { + test_frame_policy( + 'fullscreen', same_origin_src, policies[i].sameOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true); + }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + + '" and allowfullscreen.'); + test(function() { + test_frame_policy( + 'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true); + }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + + '" and allowfullscreen.'); + } + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html.sub.headers new file mode 100644 index 0000000..111121a5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-all.https.sub.html.sub.headers
@@ -0,0 +1 @@ +Feature-Policy: fullscreen *;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-self.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-self.https.sub.html new file mode 100644 index 0000000..d757d4c4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-self.https.sub.html
@@ -0,0 +1,84 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src=/feature-policy/resources/featurepolicy.js></script> + <!-- Feature-Policy: fullscreen 'self'; --> + <script> + 'use strict'; + var same_origin = 'https://{{domains[]}}:{{ports[https][0]}}'; + var cross_origin = 'https://{{domains[www]}}:{{ports[https][0]}}'; + var same_origin_src = '/feature-policy/resources/feature-policy-allowedfeatures.html'; + var cross_origin_src = cross_origin + same_origin_src; + var policies = [ + {allow: "*", sameOriginTestExpect: true, crossOriginTestExpect: true}, + {allow: "'self'", sameOriginTestExpect: true, crossOriginTestExpect: false}, + {allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false}, + {allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: true, crossOriginTestExpect: true}]; + var pipe_front = '?pipe=sub|header(Feature-Policy,fullscreen '; + var pipe_end = ';)'; + var header_policies = ["*", "'self'", "'none'"]; + + // Test that frame.policy inherits from parent's header policy when allow + // attribute is not specified. + test(function() { + test_frame_policy('fullscreen', same_origin_src, true); + }, 'Test frame policy on same origin iframe inherit from header policy.'); + test(function() { + test_frame_policy('fullscreen', cross_origin_src, false); + }, 'Test frame policy on cross origin iframe inherit from header policy.'); + + // Test frame policy with allow attribute set to be one of the policies above. + for (var i = 0; i < policies.length; i++) { + test(function() { + test_frame_policy( + 'fullscreen', same_origin_src, policies[i].sameOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + '".'); + test(function() { + test_frame_policy( + 'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + '".'); + } + + // Test that the header policy of the iframe document does not change the + // frame policy. + for (var i = 0; i < policies.length; i++) { + for (var j = 0; j < header_policies.length; j++) { + test(function() { + test_frame_policy( + 'fullscreen', + same_origin_src + pipe_front + header_policies[j] + pipe_end, + policies[i].sameOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + + '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".'); + test(function() { + test_frame_policy( + 'fullscreen', + cross_origin_src + pipe_front + header_policies[j] + pipe_end, + policies[i].crossOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + + '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".'); + } + } + + // Test that the allow attribute overrides allowfullscreen. + for (var i = 0; i < policies.length; i++) { + test(function() { + test_frame_policy( + 'fullscreen', same_origin_src, policies[i].sameOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true); + }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + + '" and allowfullscreen.'); + test(function() { + test_frame_policy( + 'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true); + }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + + '" and allowfullscreen.'); + } + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-self.https.sub.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-self.https.sub.html.sub.headers new file mode 100644 index 0000000..0cc259b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-self.https.sub.html.sub.headers
@@ -0,0 +1 @@ +Feature-Policy: fullscreen 'self';
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some.https.sub.html new file mode 100644 index 0000000..f10c66f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some.https.sub.html
@@ -0,0 +1,109 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src=/feature-policy/resources/featurepolicy.js></script> + <!-- Feature-Policy: fullscreen 'self' cross_origin https://www.example.com; --> + <script> + 'use strict'; + var same_origin = 'https://{{domains[]}}:{{ports[https][0]}}'; + var cross_origin = 'https://{{domains[www]}}:{{ports[https][0]}}'; + var cross_origin1 = 'https://{{domains[www1]}}:{{ports[https][0]}}'; + var same_origin_src = '/feature-policy/resources/feature-policy-allowedfeatures.html'; + var cross_origin_src = cross_origin + same_origin_src; + var cross_origin_src1 = cross_origin1 + same_origin_src; + // Test feature policy with same_origin_src and cross_origin_src. + var policies = [ + {allow: "*", sameOriginTestExpect: true, crossOriginTestExpect: true, crossOrigin1TestExpect: true}, + {allow: "'self'", sameOriginTestExpect: true, crossOriginTestExpect: false, crossOrigin1TestExpect: false}, + {allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false, crossOrigin1TestExpect: false}, + {allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: true, crossOriginTestExpect: true, crossOrigin1TestExpect: false}]; + var pipe_front = '?pipe=sub|header(Feature-Policy,fullscreen '; + var pipe_end = ';)'; + var header_policies = ["*", "'self'", "'none'"]; + + // Test that frame.policy inherits from parent's header policy when allow + // attribute is not specified. + test(function() { + test_frame_policy('fullscreen', same_origin_src, true); + }, 'Test frame policy on same origin iframe inherit from header policy.'); + test(function() { + test_frame_policy('fullscreen', cross_origin_src, true); + }, 'Test frame policy on cross origin iframe inherit from header policy.'); + test(function() { + test_frame_policy('fullscreen', cross_origin_src1, false); + }, 'Test frame policy on another cross origin iframe inherit from header policy.'); + + // Test frame policy with allow attribute set to be one of the policies above. + for (var i = 0; i < policies.length; i++) { + test(function() { + test_frame_policy( + 'fullscreen', same_origin_src, policies[i].sameOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + '".'); + test(function() { + test_frame_policy( + 'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + '".'); + test(function() { + test_frame_policy( + 'fullscreen', cross_origin_src1, policies[i].crossOrigin1TestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on another cross origin iframe with allow = "' + policies[i].allow + '".'); + } + + // Test that the header policy of the iframe document does not change the + // frame policy. + for (var i = 0; i < policies.length; i++) { + for (var j = 0; j < header_policies.length; j++) { + test(function() { + test_frame_policy( + 'fullscreen', + same_origin_src + pipe_front + header_policies[j] + pipe_end, + policies[i].sameOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + + '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".'); + test(function() { + test_frame_policy( + 'fullscreen', + cross_origin_src + pipe_front + header_policies[j] + pipe_end, + policies[i].crossOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + + '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".'); + test(function() { + test_frame_policy( + 'fullscreen', + cross_origin_src1 + pipe_front + header_policies[j] + pipe_end, + policies[i].crossOrigin1TestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on another cross origin iframe with allow = "' + policies[i].allow + + '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".'); + } + } + + // Test that the allow attribute overrides allowfullscreen. + for (var i = 0; i < policies.length; i++) { + test(function() { + test_frame_policy( + 'fullscreen', same_origin_src, policies[i].sameOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true); + }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + + '" and allowfullscreen.'); + test(function() { + test_frame_policy( + 'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true); + }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + + '" and allowfullscreen.'); + test(function() { + test_frame_policy( + 'fullscreen', cross_origin_src1, policies[i].crossOrigin1TestExpect, + 'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true); + }, 'Test frame policy on another cross origin iframe with allow = "' + policies[i].allow + + '" and allowfullscreen.'); + } + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some.https.sub.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some.https.sub.html.sub.headers new file mode 100644 index 0000000..c2493a0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-allowed-for-some.https.sub.html.sub.headers
@@ -0,0 +1 @@ +Feature-Policy: fullscreen 'self' https://{{domains[www]}}:{{ports[https][0]}} https://www.example.com;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-disallowed-for-all.https.sub.html b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-disallowed-for-all.https.sub.html new file mode 100644 index 0000000..e1178e7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-disallowed-for-all.https.sub.html
@@ -0,0 +1,84 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src=/feature-policy/resources/featurepolicy.js></script> + <!-- Feature-Policy: fullscreen 'none'; --> + <script> + 'use strict'; + var same_origin = 'https://{{domains[]}}:{{ports[https][0]}}'; + var cross_origin = 'https://{{domains[www]}}:{{ports[https][0]}}'; + var same_origin_src = '/feature-policy/resources/feature-policy-allowedfeatures.html'; + var cross_origin_src = cross_origin + same_origin_src; + var policies = [ + {allow: "*", sameOriginTestExpect: false, crossOriginTestExpect: false}, + {allow: "'self'", sameOriginTestExpect: false, crossOriginTestExpect: false}, + {allow: "'none'", sameOriginTestExpect: false, crossOriginTestExpect: false}, + {allow: "'self' " + cross_origin + " https://www.example.com", sameOriginTestExpect: false, crossOriginTestExpect: false}]; + var pipe_front = '?pipe=sub|header(Feature-Policy,fullscreen '; + var pipe_end = ';)'; + var header_policies = ["*", "'self'", "'none'"]; + + // Test that frame.policy inherits from parent's header policy when allow + // attribute is not specified. + test(function() { + test_frame_policy('fullscreen', same_origin_src, false); + }, 'Test frame policy on same origin iframe inherit from header policy.'); + test(function() { + test_frame_policy('fullscreen', cross_origin_src, false); + }, 'Test frame policy on cross origin iframe inherit from header policy.'); + + // Test frame policy with allow attribute set to be one of the policies above. + for (var i = 0; i < policies.length; i++) { + test(function() { + test_frame_policy( + 'fullscreen', same_origin_src, policies[i].sameOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + '".'); + test(function() { + test_frame_policy( + 'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + '".'); + } + + // Test that the header policy of the iframe document does not change the + // frame policy. + for (var i = 0; i < policies.length; i++) { + for (var j = 0; j < header_policies.length; j++) { + test(function() { + test_frame_policy( + 'fullscreen', + same_origin_src + pipe_front + header_policies[j] + pipe_end, + policies[i].sameOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + + '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".'); + test(function() { + test_frame_policy( + 'fullscreen', + cross_origin_src + pipe_front + header_policies[j] + pipe_end, + policies[i].crossOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';'); + }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + + '" and header policy = "Feature-Policy: fullscreen ' + header_policies[j] + ';".'); + } + } + + // Test that the allow attribute overrides allowfullscreen. + for (var i = 0; i < policies.length; i++) { + test(function() { + test_frame_policy( + 'fullscreen', same_origin_src, policies[i].sameOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true); + }, 'Test frame policy on same origin iframe with allow = "' + policies[i].allow + + '" and allowfullscreen.'); + test(function() { + test_frame_policy( + 'fullscreen', cross_origin_src, policies[i].crossOriginTestExpect, + 'fullscreen ' + policies[i].allow + ';', /*allowfullscreen*/true); + }, 'Test frame policy on cross origin iframe with allow = "' + policies[i].allow + + '" and allowfullscreen.'); + } + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-disallowed-for-all.https.sub.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-disallowed-for-all.https.sub.html.sub.headers new file mode 100644 index 0000000..961d4033 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/feature-policy-frame-policy-disallowed-for-all.https.sub.html.sub.headers
@@ -0,0 +1 @@ +Feature-Policy: fullscreen 'none';
diff --git a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/featurepolicy.js b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/featurepolicy.js index 925408ea..be8629d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/featurepolicy.js +++ b/third_party/WebKit/LayoutTests/external/wpt/feature-policy/resources/featurepolicy.js
@@ -383,3 +383,33 @@ }); }, test_name); } + +// This function tests that frame policy allows a given feature correctly. A +// feature is allowed in a frame either through inherited policy or specified +// by iframe allow attribute. +// Arguments: +// feature: feature name. +// src: the URL to load in the frame. +// test_expect: boolean value of whether the feature should be allowed. +// allow: optional, the allow attribute (container policy) of the iframe. +// allowfullscreen: optional, boolean value of allowfullscreen attribute. +function test_frame_policy( + feature, src, test_expect, allow, allowfullscreen) { + let frame = document.createElement('iframe'); + document.body.appendChild(frame); + // frame_policy should be dynamically updated as allow and allowfullscreen is + // updated. + var frame_policy = frame.policy; + if (typeof allow !== 'undefined') { + frame.setAttribute('allow', allow); + } + if (!!allowfullscreen) { + frame.setAttribute('allowfullscreen', true); + } + frame.src = src; + if (test_expect) { + assert_true(frame_policy.allowedFeatures().includes(feature)); + } else { + assert_false(frame_policy.allowedFeatures().includes(feature)); + } +}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/redirect/redirect-location.js b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/redirect/redirect-location.js index cb038a68..5b9a4fe 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/fetch/api/redirect/redirect-location.js +++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/api/redirect/redirect-location.js
@@ -32,7 +32,7 @@ var redirUrl = RESOURCES_DIR + "redirect.py"; var locationUrl = "top.txt"; -var invalidLocationUrl = "#invalidurl:"; +var invalidLocationUrl = "invalidurl:"; var dataLocationUrl = "data:,data%20url"; // FIXME: We may want to mix redirect-mode and cors-mode. // FIXME: Add tests for "error" redirect-mode.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/magnetometer.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/magnetometer.idl index 5ede1ec..a9ef069 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/magnetometer.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/magnetometer.idl
@@ -6,10 +6,10 @@ readonly attribute double? z; }; -enum LocalCoordinateSystem { "device", "screen" }; +enum MagnetometerLocalCoordinateSystem { "device", "screen" }; dictionary MagnetometerSensorOptions : SensorOptions { - LocalCoordinateSystem referenceFrame = "device"; + MagnetometerLocalCoordinateSystem referenceFrame = "device"; }; [Constructor(optional MagnetometerSensorOptions sensorOptions), SecureContext,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/orientation-sensor.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/orientation-sensor.idl index 2fee35d..df2ea38 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/orientation-sensor.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/orientation-sensor.idl
@@ -6,10 +6,10 @@ void populateMatrix(RotationMatrixType targetMatrix); }; -enum LocalCoordinateSystem { "device", "screen" }; +enum OrientationSensorLocalCoordinateSystem { "device", "screen" }; dictionary OrientationSensorOptions : SensorOptions { - LocalCoordinateSystem referenceFrame = "device"; + OrientationSensorLocalCoordinateSystem referenceFrame = "device"; }; [Constructor(optional OrientationSensorOptions sensorOptions), SecureContext, Exposed=Window]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method-manual.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method-manual.https.html new file mode 100644 index 0000000..caf43d1c --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method-manual.https.html
@@ -0,0 +1,196 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Tests for PaymentRequest.canMakePayment() method</title> +<link rel="help" href="https://w3c.github.io/browser-payment-api/#show-method"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +setup({ + explicit_done: true, + explicit_timeout: true, +}); + +const basicCard = Object.freeze({ supportedMethods: "basic-card" }); +const defaultMethods = Object.freeze([basicCard]); +const defaultDetails = Object.freeze({ + total: { + label: "Total", + amount: { + currency: "USD", + value: "1.00", + }, + }, +}); + +promise_test(async t => { + const request = new PaymentRequest(defaultMethods, defaultDetails); + try { + assert_true( + await request.canMakePayment(), + `canMakePaymentPromise should be true` + ); + assert_true( + await request.canMakePayment(), + `canMakePaymentPromise should be true` + ); + } catch (err) { + assert_equals( + err.name, + "NotAllowedError", + "if it throws, then it must be a NotAllowedError." + ); + } +}, `If request.[[state]] is "created", then return a promise that resolves to true for known method.`); + +promise_test(async t => { + const request = new PaymentRequest(defaultMethods, defaultDetails); + assert_true(await request.canMakePayment(), "basic-card should be supported"); +}, `If payment method identifier and serialized parts are supported, resolve promise with true.`); + +promise_test(async t => { + const unsupportedMethods = [ + "this-is-not-supported", + "https://not.supported", + "e", + "n6jzof05mk2g4lhxr-u-q-w1-c-i-pa-ty-bdvs9-ho-ae7-p-md8-s-wq3-h-qd-e-q-sa", + "a-b-q-n-s-pw0", + "m-u", + "s-l5", + "k9-f", + "m-l", + "u4-n-t", + "i488jh6-g18-fck-yb-v7-i", + "x-x-t-t-c34-o", + "https://wpt", + "https://wpt.fyi/", + "https://wpt.fyi/payment", + "https://wpt.fyi/payment-request", + "https://wpt.fyi/payment-request?", + "https://wpt.fyi/payment-request?this=is", + "https://wpt.fyi/payment-request?this=is&totally", + "https://wpt.fyi:443/payment-request?this=is&totally", + "https://wpt.fyi:443/payment-request?this=is&totally#fine", + "https://:@wpt.fyi:443/payment-request?this=is&totally#👍", + " \thttps://wpt\n ", + "https://xn--c1yn36f", + "https://點看", + ]; + for (const method of unsupportedMethods) { + try { + const request = new PaymentRequest( + [{ supportedMethods: method }], + defaultDetails + ); + assert_false( + await request.canMakePayment(), + `method "${method}" must not be supported` + ); + } catch (err) { + assert_equals( + err.name, + "NotAllowedError", + "if it throws, then it must be a NotAllowedError." + ); + } + } +}, `If payment method identifier is unknown, resolve promise with false.`); + +promise_test(async t => { + // This test might never actually hit its assertion, but that's allowed. + const request = new PaymentRequest(defaultMethods, defaultDetails); + for (let i = 0; i < 1000; i++) { + try { + await request.canMakePayment(); + } catch (err) { + assert_equals( + err.name, + "NotAllowedError", + "if it throws, then it must be a NotAllowedError." + ); + break; + } + } + for (let i = 0; i < 1000; i++) { + try { + await new PaymentRequest(defaultMethods, defaultDetails).canMakePayment(); + } catch (err) { + assert_equals( + err.name, + "NotAllowedError", + "if it throws, then it must be a NotAllowedError." + ); + break; + } + } +}, `Optionally, at the user agent's discretion, return a promise rejected with a "NotAllowedError" DOMException.`); + +function manualTest1(elem){ + elem.disabled = true; + promise_test(async t => { + const request = new PaymentRequest(defaultMethods, defaultDetails); + const acceptPromise = request.show(); // Sets state to "interactive" + const canMakePaymentPromise = request.canMakePayment(); + try { + const result = await canMakePaymentPromise; + assert_true( + false, + `canMakePaymentPromise should have thrown InvalidStateError` + ); + } catch (err) { + await promise_rejects(t, "InvalidStateError", canMakePaymentPromise); + } finally { + await request.abort(); + await promise_rejects(t, "AbortError", acceptPromise); + } + // The state should be "closed" + await promise_rejects(t, "InvalidStateError", request.canMakePayment()); + }, elem.textContent.trim()); +} + +function manualTest2(elem){ + elem.disabled = true; + promise_test(async t => { + const request = new PaymentRequest(defaultMethods, defaultDetails); + const acceptPromise = request.show(); // The state is now "interactive" + acceptPromise.catch(() => {}); // no-op, just to silence unhandled rejection in devtools. + await request.abort(); // The state is now "closed" + await promise_rejects(t, "InvalidStateError", request.canMakePayment()); + try { + const result = await request.canMakePayment(); + assert_true( + false, + `should have thrown InvalidStateError, but instead returned "${result}"` + ); + } catch (err) { + assert_equals( + err.name, + "InvalidStateError", + "must be an InvalidStateError." + ); + } + }, elem.textContent.trim()); + done(); +} +</script> + +<h2>Tests for PaymentRequest.canMakePayment() method</h2> +<p> + Click on each button in sequence from top to bottom without refreshing the page. + No payment sheet will be shown, but the tests will run in the background. +</p> +<ol> + <li> + <button onclick="manualTest1(this)"> + If request.[[state]] is "interactive", then return a promise rejected with an "InvalidStateError" DOMException. + </button> + </li> + <li> + <button onclick="manualTest2(this)"> + If request.[[state]] is "closed", then return a promise rejected with an "InvalidStateError" DOMException. + </button> + </li> +</ol> +<small> + If you find a buggy test, please <a href="https://github.com/w3c/web-platform-tests/issues">file a bug</a> + and tag one of the <a href="https://github.com/w3c/web-platform-tests/blob/master/payment-request/OWNERS">owners</a>. +</small>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https.html b/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https.html deleted file mode 100644 index 9fe0c4a..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/payment-request-canmakepayment-method.https.html +++ /dev/null
@@ -1,163 +0,0 @@ -<!DOCTYPE html> -<!-- Copyright © 2017 Chromium authors and World Wide Web Consortium, (Massachusetts Institute of Technology, ERCIM, Keio University, Beihang). --> -<meta charset="utf-8"> -<title>Tests for PaymentRequest.canMakePayment() method</title> -<link rel="help" href="https://w3c.github.io/browser-payment-api/#show-method"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script> -const basicCard = Object.freeze({ supportedMethods: "basic-card" }); -const defaultMethods = Object.freeze([basicCard]); -const defaultDetails = Object.freeze({ - total: { - label: "Total", - amount: { - currency: "USD", - value: "1.00", - }, - }, -}); - -promise_test(async t => { - const request = new PaymentRequest(defaultMethods, defaultDetails); - try { - assert_true( - await request.canMakePayment(), - `canMakePaymentPromise should be true` - ); - assert_true( - await request.canMakePayment(), - `canMakePaymentPromise should be true` - ); - } catch (err) { - assert_equals( - err.name, - "NotAllowedError", - "if it throws, then it must be a NotAllowedError." - ); - } -}, `If request.[[state]] is "created", then return a promise that resolves to true for known method.`); - -promise_test(async t => { - const request = new PaymentRequest(defaultMethods, defaultDetails); - const acceptPromise = request.show(); // Sets state to "interactive" - const canMakePaymentPromise = request.canMakePayment(); - try { - const result = await canMakePaymentPromise; - assert_true( - false, - `canMakePaymentPromise should have thrown InvalidStateError` - ); - } catch (err) { - await promise_rejects(t, "InvalidStateError", canMakePaymentPromise); - } finally { - await request.abort(); - await promise_rejects(t, "AbortError", acceptPromise); - } - // The state should be "closed" - await promise_rejects(t, "InvalidStateError", request.canMakePayment()); -}, `If request.[[state]] is "interactive", then return a promise rejected with an "InvalidStateError" DOMException.`); - -promise_test(async t => { - const request = new PaymentRequest(defaultMethods, defaultDetails); - const acceptPromise = request.show(); // The state is now "interactive" - acceptPromise.catch(() => {}); // no-op, just to silence unhandled rejection in devtools. - await request.abort(); // The state is now "closed" - await promise_rejects(t, "InvalidStateError", request.canMakePayment()); - try { - const result = await request.canMakePayment(); - assert_true( - false, - `should have thrown InvalidStateError, but instead returned "${result}"` - ); - } catch (err) { - assert_equals( - err.name, - "InvalidStateError", - "must be an InvalidStateError." - ); - } -}, `If request.[[state]] is "closed", then return a promise rejected with an "InvalidStateError" DOMException.`); - -promise_test(async t => { - const request = new PaymentRequest(defaultMethods, defaultDetails); - assert_true(await request.canMakePayment(), "basic-card should be supported"); -}, `If payment method identifier and serialized parts are supported, resolve promise with true.`); - -promise_test(async t => { - const unsupportedMethods = [ - "this-is-not-supported", - "https://not.supported", - "e", - "n6jzof05mk2g4lhxr-u-q-w1-c-i-pa-ty-bdvs9-ho-ae7-p-md8-s-wq3-h-qd-e-q-sa", - "a-b-q-n-s-pw0", - "m-u", - "s-l5", - "k9-f", - "m-l", - "u4-n-t", - "i488jh6-g18-fck-yb-v7-i", - "x-x-t-t-c34-o", - "https://wpt", - "https://wpt.fyi/", - "https://wpt.fyi/payment", - "https://wpt.fyi/payment-request", - "https://wpt.fyi/payment-request?", - "https://wpt.fyi/payment-request?this=is", - "https://wpt.fyi/payment-request?this=is&totally", - "https://wpt.fyi:443/payment-request?this=is&totally", - "https://wpt.fyi:443/payment-request?this=is&totally#fine", - "https://:@wpt.fyi:443/payment-request?this=is&totally#👍", - " \thttps://wpt\n ", - "https://xn--c1yn36f", - "https://點看", - ]; - for (const method of unsupportedMethods) { - try { - const request = new PaymentRequest( - [{ supportedMethods: method }], - defaultDetails - ); - assert_false( - await request.canMakePayment(), - `method "${method}" must not be supported` - ); - } catch (err) { - assert_equals( - err.name, - "NotAllowedError", - "if it throws, then it must be a NotAllowedError." - ); - } - } -}, `If payment method identifier is unknown, resolve promise with false.`); - -promise_test(async t => { - // This test might never actually hit its assertion, but that's allowed. - const request = new PaymentRequest(defaultMethods, defaultDetails); - for (let i = 0; i < 1000; i++) { - try { - await request.canMakePayment(); - } catch (err) { - assert_equals( - err.name, - "NotAllowedError", - "if it throws, then it must be a NotAllowedError." - ); - break; - } - } - for (let i = 0; i < 1000; i++) { - try { - await new PaymentRequest(defaultMethods, defaultDetails).canMakePayment(); - } catch (err) { - assert_equals( - err.name, - "NotAllowedError", - "if it throws, then it must be a NotAllowedError." - ); - break; - } - } -}, `Optionally, at the user agent's discretion, return a promise rejected with a "NotAllowedError" DOMException.`); -</script>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/acid2-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/acid2-expected.png index 6f6b714..58d9f9e 100644 --- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/acid2-expected.png +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/css/acid2-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html index 9e6a7ff6..ce3a8eb 100644 --- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html +++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-create-basics.html
@@ -25,121 +25,61 @@ navigator.credentials.create({publicKey : MAKE_CREDENTIAL_OPTIONS})); }, "Verify that invalid domain error returned by mock is properly handled."); -promise_test(t => { - var customMakeCredOptions = { - // No challenge. - rp: PUBLIC_KEY_RP, - user: PUBLIC_KEY_USER, - pubKeyCredParams: PUBLIC_KEY_PARAMETERS, - }; - return promise_rejects(t, new TypeError(), - navigator.credentials.create({publicKey : customMakeCredOptions})); +promise_test(t => { + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); + delete customMakeCredOptions.challenge; + return promise_rejects(t, new TypeError(), + navigator.credentials.create({publicKey : customMakeCredOptions})); }, "navigator.credentials.create() with missing challenge"); promise_test(t => { - var customMakeCredOptions = { - challenge: CHALLENGE, - rp: PUBLIC_KEY_RP, - user: PUBLIC_KEY_USER, - // No parameters. - authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA, - }; - - return promise_rejects(t, new TypeError(), - navigator.credentials.create({publicKey : customMakeCredOptions})); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); + delete customMakeCredOptions.pubKeyCredParams; + return promise_rejects(t, new TypeError(), + navigator.credentials.create({publicKey : customMakeCredOptions})); }, "navigator.credentials.create() with missing parameters"); promise_test(t => { - var customMakeCredOptions = { - challenge: CHALLENGE, - // No rp. - user: PUBLIC_KEY_USER, - pubKeyCredParams: PUBLIC_KEY_PARAMETERS, - authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA, - }; - - return promise_rejects(t, new TypeError(), - navigator.credentials.create({publicKey: customMakeCredOptions})); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); + delete customMakeCredOptions.rp; + return promise_rejects(t, new TypeError(), + navigator.credentials.create({publicKey: customMakeCredOptions})); }, "navigator.credentials.create() with missing rp"); promise_test(t => { - var customMakeCredOptions = { - challenge: CHALLENGE, - rp: PUBLIC_KEY_RP, - // No user. - pubKeyCredParams: PUBLIC_KEY_PARAMETERS, - authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA, - }; - - return promise_rejects(t, new TypeError(), - navigator.credentials.create({publicKey: customMakeCredOptions})); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); + delete customMakeCredOptions.user; + return promise_rejects(t, new TypeError(), + navigator.credentials.create({publicKey: customMakeCredOptions})); }, "navigator.credentials.create() with missing user"); promise_test(t => { - var customMakeCredOptions = { - challenge: CHALLENGE, - rp: { id: "google.com" }, - user: PUBLIC_KEY_USER, - pubKeyCredParams: PUBLIC_KEY_PARAMETERS, - authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA, - }; - - return promise_rejects(t, new TypeError(), - navigator.credentials.create({publicKey: customMakeCredOptions})); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); + delete customMakeCredOptions.rp.name; + return promise_rejects(t, new TypeError(), + navigator.credentials.create({publicKey: customMakeCredOptions})); }, "navigator.credentials.create() with missing rp.name"); promise_test(t => { - var customMakeCredOptions = { - challenge: CHALLENGE, - rp: PUBLIC_KEY_RP, - user: { - name: "avery.a.jones@example.com", - displayName: "Avery A. Jones", - icon: "https://pics.acme.com/00/p/aBjjjpqPb.png" - }, - pubKeyCredParams: PUBLIC_KEY_PARAMETERS, - authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA, - }; - - return promise_rejects(t, new TypeError(), - navigator.credentials.create({publicKey: customMakeCredOptions})); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); + delete customMakeCredOptions.user.id; + return promise_rejects(t, new TypeError(), + navigator.credentials.create({publicKey: customMakeCredOptions})); }, "navigator.credentials.create() with missing user.id"); promise_test(t => { - var customMakeCredOptions = { - challenge: CHALLENGE, - rp: PUBLIC_KEY_RP, - user: { - id: new TextEncoder().encode("1098237235409872"), - displayName: "Avery A. Jones", - icon: "https://pics.acme.com/00/p/aBjjjpqPb.png" - }, - pubKeyCredParams: PUBLIC_KEY_PARAMETERS, - timeout: 60000, // 1 minute - authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA, - excludeCredentials: [], // No already-registered credentials. - }; - - return promise_rejects(t, new TypeError(), - navigator.credentials.create({publicKey: customMakeCredOptions})); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); + delete customMakeCredOptions.user.name; + return promise_rejects(t, new TypeError(), + navigator.credentials.create({publicKey: customMakeCredOptions})); }, "navigator.credentials.create() with missing user.name"); promise_test(t => { - var customMakeCredOptions = { - challenge: CHALLENGE, - rp: PUBLIC_KEY_RP, - user: { - id: new TextEncoder().encode("1098237235409872"), - name: "avery.a.jones@example.com", - icon: "https://pics.acme.com/00/p/aBjjjpqPb.png" - }, - pubKeyCredParams: PUBLIC_KEY_PARAMETERS, - authenticatorSelection: AUTHENTICATOR_SELECTION_CRITERIA, - }; - - return promise_rejects(t, new TypeError(), - navigator.credentials.create({publicKey: customMakeCredOptions})); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); +delete customMakeCredOptions.user.displayName; + return promise_rejects(t, new TypeError(), + navigator.credentials.create({publicKey: customMakeCredOptions})); }, "navigator.credentials.create() with missing user.displayName"); promise_test(_ => { @@ -150,9 +90,9 @@ mockAuthenticator.setAuthenticatorStatus( webauth.mojom.AuthenticatorStatus.SUCCESS); - return navigator.credentials.create({publicKey : MAKE_CREDENTIAL_OPTIONS}).then(r => { - assertValidMakeCredentialResponse(r); - }); + return navigator.credentials.create({publicKey : MAKE_CREDENTIAL_OPTIONS}).then(r => { + assertValidMakeCredentialResponse(r); + }); }, "Verify that the mock returns the values we give it."); promise_test(t => { @@ -185,29 +125,18 @@ promise_test(_ => { mockAuthenticator.reset(); - mockAuthenticator.setRawId(RAW_ID); - mockAuthenticator.setId(ID); - mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON); - mockAuthenticator.setAttestationObject(ATTESTATION_OBJECT); - mockAuthenticator.setAuthenticatorStatus( - webauth.mojom.AuthenticatorStatus.SUCCESS); - - var customPublicKey = { - challenge: CHALLENGE, - rp: { name: "Acme" }, - user: PUBLIC_KEY_USER, - pubKeyCredParams: PUBLIC_KEY_PARAMETERS, - }; - - return navigator.credentials.create({publicKey: customPublicKey}).then(r => { - assertValidMakeCredentialResponse(r); - }); + mockAuthenticator.setDefaultsForSuccessfulMakeCredential(); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); + customMakeCredOptions.rp = { name: "Acme" }; + return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => { + assertValidMakeCredentialResponse(r); + }); }, "navigator.credentials.create() with missing rp.id"); promise_test(_ => { mockAuthenticator.reset(); mockAuthenticator.setDefaultsForSuccessfulMakeCredential(); - var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); delete customMakeCredOptions.authenticatorSelection; return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => { assertValidMakeCredentialResponse(r); @@ -217,7 +146,7 @@ promise_test(_ => { mockAuthenticator.reset(); mockAuthenticator.setDefaultsForSuccessfulMakeCredential(); - var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); delete customMakeCredOptions.authenticatorSelection.requireResidentKey; return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => { assertValidMakeCredentialResponse(r); @@ -227,7 +156,7 @@ promise_test(_ => { mockAuthenticator.reset(); mockAuthenticator.setDefaultsForSuccessfulMakeCredential(); - var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); delete customMakeCredOptions.authenticatorSelection.userVerification; return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => { assertValidMakeCredentialResponse(r); @@ -238,25 +167,25 @@ mockAuthenticator.reset(); mockAuthenticator.setAuthenticatorStatus( webauth.mojom.AuthenticatorStatus.NOT_SUPPORTED_ERROR); - var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); return promise_rejects(t, "NotSupportedError", - navigator.credentials.create({publicKey: customMakeCredOptions})); + navigator.credentials.create({publicKey: customMakeCredOptions})); }, "navigator.credentials.create() with requireResidentKey true"); promise_test(t => { mockAuthenticator.reset(); mockAuthenticator.setAuthenticatorStatus( webauth.mojom.AuthenticatorStatus.NOT_SUPPORTED_ERROR); - var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); customMakeCredOptions.authenticatorSelection.userVerification = 'required'; return promise_rejects(t, "NotSupportedError", - navigator.credentials.create({publicKey: customMakeCredOptions})); + navigator.credentials.create({publicKey: customMakeCredOptions})); }, "navigator.credentials.create() with userVerification required"); promise_test(_ => { mockAuthenticator.reset(); mockAuthenticator.setDefaultsForSuccessfulMakeCredential(); - var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); customMakeCredOptions.authenticatorSelection.userVerification = 'discouraged'; return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => { assertValidMakeCredentialResponse(r); @@ -266,7 +195,7 @@ promise_test(_ => { mockAuthenticator.reset(); mockAuthenticator.setDefaultsForSuccessfulMakeCredential(); - var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); customMakeCredOptions.authenticatorSelection.authenticatorAttachment = 'platform'; return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => { assertValidMakeCredentialResponse(r); @@ -276,10 +205,11 @@ promise_test(_ => { mockAuthenticator.reset(); mockAuthenticator.setDefaultsForSuccessfulMakeCredential(); - var customMakeCredOptions = Object.assign({}, MAKE_CREDENTIAL_OPTIONS); + var customMakeCredOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); customMakeCredOptions.authenticatorSelection.authenticatorAttachment = 'cross-platform'; return navigator.credentials.create({publicKey: customMakeCredOptions}).then(r => { assertValidMakeCredentialResponse(r); }); }, "navigator.credentials.create() with cross-platform authenticatorAttachment"); + </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html index a48283c..63f3e8e 100644 --- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html +++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/credentialscontainer-get-basics.html
@@ -115,16 +115,10 @@ promise_test(_ => { mockAuthenticator.setRawId(RAW_ID); - mockAuthenticator.setId(ID); - mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON); - mockAuthenticator.setAuthenticatorData(AUTHENTICATOR_DATA); - mockAuthenticator.setSignature(SIGNATURE); - mockAuthenticator.setAuthenticatorStatus( - webauth.mojom.AuthenticatorStatus.SUCCESS); - - return navigator.credentials.get({publicKey : GET_CREDENTIAL_OPTIONS}).then(r => { - assertValidGetCredentialResponse(r); - }); + mockAuthenticator.setDefaultsForSuccessfulGetAssertion(); + return navigator.credentials.get({publicKey : GET_CREDENTIAL_OPTIONS}).then(r => { + assertValidGetCredentialResponse(r); + }); }, "Verify that mockAuthenticator returns the values we give it."); promise_test(t => { @@ -156,54 +150,28 @@ }, "Verify that not supported error returned by mock is properly handled."); promise_test(function(t) { - var customGetCredentialOptions = { - // No challenge. - rpId: "google.com", - allowCredentials: [ACCEPTABLE_CREDENTIAL], - userVerification: "preferred", - }; - - return promise_rejects(t, new TypeError(), - navigator.credentials.get({publicKey: customGetCredentialOptions})); + var customGetCredentialOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); + delete customGetCredentialOptions.challenge; + return promise_rejects(t, new TypeError(), + navigator.credentials.get({publicKey: customGetCredentialOptions})); }, "navigator.credentials.get() with missing challenge"); promise_test(_ => { mockAuthenticator.reset(); - mockAuthenticator.setRawId(RAW_ID); - mockAuthenticator.setId(ID); - mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON); - mockAuthenticator.setAuthenticatorData(AUTHENTICATOR_DATA); - mockAuthenticator.setSignature(SIGNATURE); - mockAuthenticator.setAuthenticatorStatus( - webauth.mojom.AuthenticatorStatus.SUCCESS); - - var customPublicKey = { - challenge: CHALLENGE, - allowCredentials: [ACCEPTABLE_CREDENTIAL], - userVerification: "preferred", - }; - - return navigator.credentials.get({publicKey: customPublicKey}).then(r => { + mockAuthenticator.setDefaultsForSuccessfulGetAssertion(); + var customGetCredentialOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); + delete customGetCredentialOptions.rpId; + return navigator.credentials.get({publicKey: customGetCredentialOptions}).then(r => { assertValidGetCredentialResponse(r); }); }, "navigator.credentials.get() with missing rpId"); promise_test(_ => { mockAuthenticator.reset(); - mockAuthenticator.setRawId(RAW_ID); - mockAuthenticator.setId(ID); - mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON); - mockAuthenticator.setAuthenticatorData(AUTHENTICATOR_DATA); - mockAuthenticator.setSignature(SIGNATURE); - mockAuthenticator.setAuthenticatorStatus( - webauth.mojom.AuthenticatorStatus.SUCCESS); - - var customPublicKey = { - challenge: CHALLENGE, - allowCredentials: [ACCEPTABLE_CREDENTIAL] - }; - - return navigator.credentials.get({publicKey: customPublicKey}).then(r => { + mockAuthenticator.setDefaultsForSuccessfulGetAssertion(); + var customGetCredentialOptions = deepCopy(MAKE_CREDENTIAL_OPTIONS); + delete customGetCredentialOptions.userVerification; + return navigator.credentials.get({publicKey: customGetCredentialOptions}).then(r => { assertValidGetCredentialResponse(r); }); }, "navigator.credentials.get() with missing user verification requirement");
diff --git a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/credential-helpers.js b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/credential-helpers.js index 9257ef3..aa8bfd1 100644 --- a/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/credential-helpers.js +++ b/third_party/WebKit/LayoutTests/http/tests/credentialmanager/resources/credential-helpers.js
@@ -138,6 +138,17 @@ webauth.mojom.AuthenticatorStatus.SUCCESS); } + // Sets everything needed for a GetAssertion success response. + setDefaultsForSuccessfulGetAssertion() { + mockAuthenticator.setRawId(RAW_ID); + mockAuthenticator.setId(ID); + mockAuthenticator.setClientDataJson(CLIENT_DATA_JSON); + mockAuthenticator.setAuthenticatorData(AUTHENTICATOR_DATA); + mockAuthenticator.setSignature(SIGNATURE); + mockAuthenticator.setAuthenticatorStatus( + webauth.mojom.AuthenticatorStatus.SUCCESS); + } + setAuthenticatorStatus(status) { this.status_ = status; } @@ -267,6 +278,16 @@ return "<script>" + code + "</scr" + "ipt>"; } +function deepCopy(value) { + if ([Number, String, Uint8Array].includes(value.constructor)) + return value; + + let copy = (value.constructor == Array) ? [] : {}; + for (let key of Object.keys(value)) + copy[key] = deepCopy(value[key]); + return copy; +} + // Verifies if |r| is the valid response to credentials.create(publicKey). function assertValidMakeCredentialResponse(r) { assert_equals(r.id, ID, 'id');
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler-expected.txt index fd7f45ad..23be5236 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler-expected.txt
@@ -1,3 +1,3 @@ Tests that Debugger.stepInto doesn't ignore inline event listeners. -functionName (should be empty): empty +functionName (should be onclick): onclick
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-paintOrder-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-paintOrder-expected.txt new file mode 100644 index 0000000..2545d4e --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-paintOrder-expected.txt
@@ -0,0 +1,13 @@ +Tests DOMSnapshot.getSnapshot method returning paint order indexes. +box3 +box2 +box5 +box6 +box4 +box1 +box7 +iframe +mydiv +shadow-host +shadow-div +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-paintOrder.js b/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-paintOrder.js new file mode 100644 index 0000000..8aac438 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-paintOrder.js
@@ -0,0 +1,42 @@ +(async function(testRunner) { + var {page, session, dp} = await testRunner.startURL('../resources/stacking_context.html', 'Tests DOMSnapshot.getSnapshot method returning paint order indexes.'); + + await session.evaluate(` + var host = document.querySelector('#shadow-host').attachShadow({mode: 'open'}); + var template = document.querySelector('#shadow-template'); + host.appendChild(template.content); + template.remove(); + document.body.offsetWidth; + `); + + function logPaintOrderList(result) { + let entries = []; + + for (const layout_node of result.layoutTreeNodes) { + let attrs = result.domNodes[layout_node.domNodeIndex].attributes; + if (!attrs) continue; + for (const attr of attrs) { + if (attr.name === 'id') { + entries.push({ + 'id': attr.value, + 'paintOrder': layout_node.paintOrder + }); + break; + } + } + } + + entries.sort(function(a, b) { + return a['paintOrder'] - b['paintOrder']; + }).forEach(function(e) { + testRunner.log(e['id']); + }); + } + + var response = await dp.DOMSnapshot.getSnapshot({'computedStyleWhitelist': [], 'includePaintOrder': true}); + if (response.error) + testRunner.log(response); + else + logPaintOrderList(response.result); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/resources/stacking_context.html b/third_party/WebKit/LayoutTests/inspector-protocol/resources/stacking_context.html new file mode 100644 index 0000000..5093d03 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/resources/stacking_context.html
@@ -0,0 +1,81 @@ +<html> +<head> + <style> + * { + margin: 0px; + } + div { + position: absolute; + padding-top: 20px; + border: 1px solid black; + color: white; + text-align: center; + } + #box1 { + z-index: 5; + background-color: rgba(200, 100, 100, 0.9); + width: 100px; + height: 400px; + } + #box2 { + z-index: 4; + background-color: rgba(100, 200, 100, 0.9); + width: 560px; + height: 300px; + top: 50px; + left: 70px; + } + #box3 { + z-index: 2; + background-color: rgba(200, 100, 100, 0.9); + width: 100px; + height: 400px; + left: 600px; + } + #box4 { + z-index: 6; + background-color: rgba(100, 100, 200, 0.9); + left: 20px; + width: 100px; + height: 220px; + padding-left: 0px; + } + #box5 { + z-index: 1; + background-color: rgba(100, 100, 200, 0.9); + left: 440px; + width: 100px; + height: 220px; + } + #box6 { + z-index: 3; + background-color: rgba(100, 200, 200, 0.9); + left: 80px; + top: 120px; + width: 400px; + height: 100px; + } + #box7 { + z-index: 5; + top: 500px; + } + </style> + <template id="shadow-template"> + <div id="shadow-div">Hi!</div> + </template> +</head> +<body> +<div id="box1">Box1</div> +<div id="box2"> + Box2 + <div id="box4">Box4</div> + <div id="box5">Box5</div> + <div id="box6">Box6</div> +</div> +<div id="box3">Box3</div> +<div id="box7"> + <iframe src='./iframe.html' width="400" height="200" id="iframe"></iframe> + <div id="shadow-host"></div> +</div> +</body> +</html> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/resources/testharnessreport.js b/third_party/WebKit/LayoutTests/resources/testharnessreport.js index 0a3a940..2774eb94 100644 --- a/third_party/WebKit/LayoutTests/resources/testharnessreport.js +++ b/third_party/WebKit/LayoutTests/resources/testharnessreport.js
@@ -27,12 +27,21 @@ testRunner.setCloseRemainingWindowsWhenComplete(true); testRunner.setDumpJavaScriptDialogs(false); - // fetch-event-referrer-policy.https.html intentionally loads mixed - // content in order to test the referrer policy, so - // WebKitAllowRunningInsecureContent must be set to true or else the - // load would be blocked. - if (document.URL.indexOf('service-workers/service-worker/fetch-event-referrer-policy.https.html') >= 0) { + // Some tests intentionally load mixed content in order to test the + // referrer policy, so WebKitAllowRunningInsecureContent must be set + // to true or else the load would be blocked. + const paths = [ + 'service-workers/service-worker/fetch-event-referrer-policy.https.html', + 'beacon/headers/header-referrer-no-referrer-when-downgrade.https.html', + 'beacon/headers/header-referrer-strict-origin-when-cross-origin.https.html', + 'beacon/headers/header-referrer-strict-origin.https.html', + 'beacon/headers/header-referrer-unsafe-url.https.html', + ]; + for (const path of paths) { + if (document.URL.endsWith(path)) { testRunner.overridePreference('WebKitAllowRunningInsecureContent', true); + break; + } } }
diff --git a/third_party/WebKit/Source/bindings/scripts/scripts.gni b/third_party/WebKit/Source/bindings/scripts/scripts.gni index 50a33e7f..07cba88 100644 --- a/third_party/WebKit/Source/bindings/scripts/scripts.gni +++ b/third_party/WebKit/Source/bindings/scripts/scripts.gni
@@ -212,88 +212,50 @@ "//third_party/WebKit/Source/core:generated_testing_idls", ] - # On mac spawning a python process per IDL file is slow. Use a single action - # instead. - # TODO(bashi,tikuta): Use a pool when crbug.com/635308 is fixed. - if (is_mac) { - action(target_name) { - script = _script - inputs = _inputs - public_deps = _public_deps + # Spawning a python process per IDL file is slow. Use a single action + # instead (crbug.com/821256). + action(target_name) { + script = _script + inputs = _inputs + public_deps = _public_deps - sources = invoker.sources - outputs = [] - foreach(_source, sources) { - _name_part = get_path_info(_source, "name") - if (snake_case_source_files) { - outputs += [ - "$output_dir/v8_${_name_part}${output_name_suffix}.cc", - "$output_dir/v8_${_name_part}${output_name_suffix}.h", - ] - } else { - outputs += [ - "$output_dir/V8${_name_part}${output_name_suffix}.cpp", - "$output_dir/V8${_name_part}${output_name_suffix}.h", - ] - } - } - - idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp" - write_file(idl_files_list, rebase_path(invoker.sources, root_build_dir)) - inputs += [ idl_files_list ] - - args = [] + sources = invoker.sources + outputs = [] + foreach(_source, sources) { + _name_part = get_path_info(_source, "name") if (snake_case_source_files) { - args += [ "--snake-case-generated-files" ] - } - args += [ - "--cache-dir", - rebase_path(bindings_scripts_output_dir, root_build_dir), - "--output-dir", - rebase_path(output_dir, root_build_dir), - "--info-dir", - rebase_path("$bindings_output_dir", root_build_dir), - "--target-component", - invoker.target_component, - "--read-idl-list-from-file", - rebase_path(idl_files_list, root_build_dir), - ] - } - } else { - action_foreach(target_name) { - script = _script - inputs = _inputs - public_deps = _public_deps - - sources = invoker.sources - if (snake_case_source_files) { - outputs = [ - "$output_dir/v8_{{source_name_part}}${output_name_suffix}.cc", - "$output_dir/v8_{{source_name_part}}${output_name_suffix}.h", + outputs += [ + "$output_dir/v8_${_name_part}${output_name_suffix}.cc", + "$output_dir/v8_${_name_part}${output_name_suffix}.h", ] } else { - outputs = [ - "$output_dir/V8{{source_name_part}}${output_name_suffix}.cpp", - "$output_dir/V8{{source_name_part}}${output_name_suffix}.h", + outputs += [ + "$output_dir/V8${_name_part}${output_name_suffix}.cpp", + "$output_dir/V8${_name_part}${output_name_suffix}.h", ] } - - args = [] - if (snake_case_source_files) { - args += [ "--snake-case-generated-files" ] - } - args += [ - "--cache-dir", - rebase_path(bindings_scripts_output_dir, root_build_dir), - "--output-dir", - rebase_path(output_dir, root_build_dir), - "--info-dir", - rebase_path("$bindings_output_dir", root_build_dir), - "--target-component", - invoker.target_component, - "{{source}}", - ] } + + idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp" + write_file(idl_files_list, rebase_path(invoker.sources, root_build_dir)) + inputs += [ idl_files_list ] + + args = [] + if (snake_case_source_files) { + args += [ "--snake-case-generated-files" ] + } + args += [ + "--cache-dir", + rebase_path(bindings_scripts_output_dir, root_build_dir), + "--output-dir", + rebase_path(output_dir, root_build_dir), + "--info-dir", + rebase_path("$bindings_output_dir", root_build_dir), + "--target-component", + invoker.target_component, + "--read-idl-list-from-file", + rebase_path(idl_files_list, root_build_dir), + ] } }
diff --git a/third_party/WebKit/Source/bindings/scripts/utilities.py b/third_party/WebKit/Source/bindings/scripts/utilities.py index b3b43597..7f89901 100644 --- a/third_party/WebKit/Source/bindings/scripts/utilities.py +++ b/third_party/WebKit/Source/bindings/scripts/utilities.py
@@ -525,14 +525,18 @@ output = [] for line in text.split('\n'): # Skip empty lines. - if re_empty_line.match(line): + if line == '' or re_empty_line.match(line): was_empty_line = True continue # Emit a single empty line if needed. if was_empty_line: was_empty_line = False - match = re_first_brace.search(line) + if '}' in line: + match = re_first_brace.search(line) + else: + match = None + if was_open_brace: # No empty line just after an open brace. pass @@ -547,7 +551,10 @@ output.append(line) # Remember an open brace. - match = re_last_brace.search(line) + if '{' in line: + match = re_last_brace.search(line) + else: + match = None was_open_brace = (match and match.group('last') == '{' and 'namespace' not in line) # Let |'\n'.join| emit the last newline.
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp index e2407f83..ad5d8da 100644 --- a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp +++ b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
@@ -519,7 +519,7 @@ Keyframe::PropertySpecificKeyframe* keyframe, const AnimatableValue* value, const TimingFunction& keyframe_timing_function) { - FilterEffectBuilder builder(nullptr, FloatRect(), 1); + FilterEffectBuilder builder(FloatRect(), 1); CompositorFilterKeyframe filter_keyframe( keyframe->Offset(), builder.BuildFilterOperations(
diff --git a/third_party/WebKit/Source/core/css/CSSURIValue.cpp b/third_party/WebKit/Source/core/css/CSSURIValue.cpp index 908ff91c..e476f957 100644 --- a/third_party/WebKit/Source/core/css/CSSURIValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSURIValue.cpp
@@ -6,9 +6,8 @@ #include "core/css/CSSMarkup.h" #include "core/dom/Document.h" -#include "core/svg/SVGElementProxy.h" +#include "core/svg/SVGResource.h" #include "platform/weborigin/KURL.h" -#include "platform/wtf/text/WTFString.h" namespace blink { @@ -24,16 +23,10 @@ CSSURIValue::~CSSURIValue() = default; -SVGElementProxy& CSSURIValue::EnsureElementProxy( - const Document& document) const { - if (proxy_) - return *proxy_; - AtomicString fragment_id = FragmentIdentifier(); - if (IsLocal(document)) - proxy_ = SVGElementProxy::Create(fragment_id); - else - proxy_ = SVGElementProxy::Create(absolute_url_, fragment_id); - return *proxy_; +SVGResource* CSSURIValue::EnsureResourceReference() const { + if (!resource_) + resource_ = new ExternalSVGResource(AbsoluteUrl()); + return resource_; } void CSSURIValue::ReResolveUrl(const Document& document) const { @@ -44,7 +37,7 @@ if (url_string == absolute_url_) return; absolute_url_ = url_string; - proxy_ = nullptr; + resource_ = nullptr; } String CSSURIValue::CustomCSSText() const { @@ -76,7 +69,7 @@ } void CSSURIValue::TraceAfterDispatch(blink::Visitor* visitor) { - visitor->Trace(proxy_); + visitor->Trace(resource_); CSSValue::TraceAfterDispatch(visitor); }
diff --git a/third_party/WebKit/Source/core/css/CSSURIValue.h b/third_party/WebKit/Source/core/css/CSSURIValue.h index 743c65e4..e8b9064 100644 --- a/third_party/WebKit/Source/core/css/CSSURIValue.h +++ b/third_party/WebKit/Source/core/css/CSSURIValue.h
@@ -12,7 +12,7 @@ class Document; class KURL; -class SVGElementProxy; +class SVGResource; class CSSURIValue : public CSSValue { public: @@ -24,7 +24,7 @@ } ~CSSURIValue(); - SVGElementProxy& EnsureElementProxy(const Document&) const; + SVGResource* EnsureResourceReference() const; void ReResolveUrl(const Document&) const; const String& Value() const { return relative_url_; } @@ -48,7 +48,7 @@ AtomicString relative_url_; bool is_local_; - mutable Member<SVGElementProxy> proxy_; + mutable Member<SVGResource> resource_; mutable AtomicString absolute_url_; };
diff --git a/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp b/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp index c0e5299..eb10e745 100644 --- a/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp +++ b/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp
@@ -39,7 +39,6 @@ #include "core/style/StyleGeneratedImage.h" #include "core/style/StyleImage.h" #include "core/style/StylePendingImage.h" -#include "core/svg/SVGElementProxy.h" #include "core/svg/SVGTreeScopeResources.h" #include "platform/Length.h" #include "platform/loader/fetch/FetchParameters.h" @@ -97,22 +96,21 @@ return value.CachedImage(); } -SVGElementProxy& ElementStyleResources::CachedOrPendingFromValue( - const CSSURIValue& value) { - return value.EnsureElementProxy(*document_); -} - SVGResource* ElementStyleResources::GetSVGResourceFromValue( TreeScope& tree_scope, - const CSSURIValue& value) const { - if (!value.IsLocal(*document_)) - return nullptr; - SVGTreeScopeResources& tree_scope_resources = - tree_scope.EnsureSVGTreeScopedResources(); - return tree_scope_resources.ResourceForId(value.FragmentIdentifier()); + const CSSURIValue& value, + AllowExternal allow_external) const { + if (value.IsLocal(*document_)) { + SVGTreeScopeResources& tree_scope_resources = + tree_scope.EnsureSVGTreeScopedResources(); + return tree_scope_resources.ResourceForId(value.FragmentIdentifier()); + } + if (allow_external == kAllowExternalResource) + return value.EnsureResourceReference(); + return nullptr; } -void ElementStyleResources::LoadPendingSVGDocuments( +void ElementStyleResources::LoadPendingSVGResources( ComputedStyle* computed_style) { if (!computed_style->HasFilter()) return; @@ -123,7 +121,8 @@ continue; ReferenceFilterOperation& reference_operation = ToReferenceFilterOperation(*filter_operation); - reference_operation.ElementProxy().Resolve(*document_); + if (SVGResource* resource = reference_operation.Resource()) + resource->Load(*document_); } } @@ -311,7 +310,7 @@ void ElementStyleResources::LoadPendingResources( ComputedStyle* computed_style) { LoadPendingImages(computed_style); - LoadPendingSVGDocuments(computed_style); + LoadPendingSVGResources(computed_style); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h b/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h index 46cc179..29e8a15 100644 --- a/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h +++ b/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h
@@ -43,7 +43,6 @@ class CSSValue; class ComputedStyle; class Document; -class SVGElementProxy; class SVGResource; class StyleImage; class StylePendingImage; @@ -60,8 +59,12 @@ StyleImage* GetStyleImage(CSSPropertyID, const CSSValue&); StyleImage* CachedOrPendingFromValue(CSSPropertyID, const CSSImageValue&); StyleImage* SetOrPendingFromValue(CSSPropertyID, const CSSImageSetValue&); - SVGElementProxy& CachedOrPendingFromValue(const CSSURIValue&); - SVGResource* GetSVGResourceFromValue(TreeScope&, const CSSURIValue&) const; + + enum AllowExternal { kDontAllowExternalResource, kAllowExternalResource }; + SVGResource* GetSVGResourceFromValue( + TreeScope&, + const CSSURIValue&, + AllowExternal = kDontAllowExternalResource) const; void LoadPendingResources(ComputedStyle*); @@ -69,7 +72,7 @@ StyleImage* GeneratedOrPendingFromValue(CSSPropertyID, const CSSImageGeneratorValue&); - void LoadPendingSVGDocuments(ComputedStyle*); + void LoadPendingSVGResources(ComputedStyle*); void LoadPendingImages(ComputedStyle*); StyleImage* LoadPendingImage(
diff --git a/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp b/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp index 852ef8d..7cbeda3 100644 --- a/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp +++ b/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp
@@ -138,10 +138,12 @@ CountFilterUse(FilterOperation::REFERENCE, state.GetDocument()); const CSSURIValue& url_value = ToCSSURIValue(*curr_value); - SVGElementProxy& element_proxy = - state.GetElementStyleResources().CachedOrPendingFromValue(url_value); + SVGResource* resource = + state.GetElementStyleResources().GetSVGResourceFromValue( + state.GetTreeScope(), url_value, + ElementStyleResources::kAllowExternalResource); operations.Operations().push_back( - ReferenceFilterOperation::Create(url_value.Value(), element_proxy)); + ReferenceFilterOperation::Create(url_value.Value(), resource)); continue; }
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNode.cpp b/third_party/WebKit/Source/core/dom/AccessibleNode.cpp index f4bb1644..89b6acf 100644 --- a/third_party/WebKit/Source/core/dom/AccessibleNode.cpp +++ b/third_party/WebKit/Source/core/dom/AccessibleNode.cpp
@@ -991,6 +991,13 @@ return; } + if (child->parent_) { + exception_state.ThrowDOMException(kNotSupportedError, + "Reparenting is not supported yet."); + return; + } + child->parent_ = this; + if (!GetDocument()->GetSecurityOrigin()->CanAccess( child->GetDocument()->GetSecurityOrigin())) { exception_state.ThrowDOMException( @@ -1036,7 +1043,13 @@ } ExecutionContext* AccessibleNode::GetExecutionContext() const { - return element_->GetExecutionContext(); + if (element_) + return element_->GetExecutionContext(); + + if (parent_) + return parent_->GetExecutionContext(); + + return nullptr; } void AccessibleNode::SetStringProperty(AOMStringProperty property, @@ -1144,6 +1157,7 @@ visitor->Trace(relation_properties_); visitor->Trace(relation_list_properties_); visitor->Trace(children_); + visitor->Trace(parent_); EventTargetWithInlineData::Trace(visitor); }
diff --git a/third_party/WebKit/Source/core/dom/AccessibleNode.h b/third_party/WebKit/Source/core/dom/AccessibleNode.h index 0dbd53f..efd24ff 100644 --- a/third_party/WebKit/Source/core/dom/AccessibleNode.h +++ b/third_party/WebKit/Source/core/dom/AccessibleNode.h
@@ -388,6 +388,10 @@ // This object's AccessibleNode children, which must be only virtual // AccessibleNodes (with no associated Element). HeapVector<Member<AccessibleNode>> children_; + + // This object's AccessibleNode parent. Only set if this is a + // virtual AccessibleNode that's in the tree. + Member<AccessibleNode> parent_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp index 68b2f68..b507df3a 100644 --- a/third_party/WebKit/Source/core/dom/Element.cpp +++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -3659,7 +3659,11 @@ if (style.Display() == EDisplay::kContents && !NeedsReattachLayoutTree()) DCHECK(!GetLayoutObject() || IsPseudoElement()); #endif - + if (IsSVGElement()) { + Element* parent_element = LayoutTreeBuilderTraversal::ParentElement(*this); + if (parent_element && !parent_element->IsSVGElement()) + return false; + } return style.Display() == EDisplay::kContents || IsHTMLOptGroupElement(*this) || IsHTMLOptionElement(*this) || IsSVGStopElement(*this);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp index 16111e73..ce251aa2 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.cpp
@@ -30,9 +30,14 @@ #include "core/inspector/InspectedFrames.h" #include "core/inspector/InspectorDOMAgent.h" #include "core/inspector/InspectorDOMDebuggerAgent.h" +#include "core/layout/LayoutEmbeddedContent.h" #include "core/layout/LayoutObject.h" #include "core/layout/LayoutText.h" +#include "core/layout/LayoutView.h" #include "core/layout/line/InlineTextBox.h" +#include "core/paint/PaintLayer.h" +#include "core/paint/PaintLayerStackingNode.h" +#include "core/paint/PaintLayerStackingNodeIterator.h" #include "platform/wtf/PtrUtil.h" namespace blink { @@ -52,6 +57,19 @@ .build(); } +Document* GetEmbeddedDocument(PaintLayer* layer) { + // Documents are embedded on their own PaintLayer via a LayoutEmbeddedContent. + if (layer->GetLayoutObject().IsLayoutEmbeddedContent()) { + FrameView* frame_view = + ToLayoutEmbeddedContent(layer->GetLayoutObject()).ChildFrameView(); + if (frame_view && frame_view->IsLocalFrameView()) { + LocalFrameView* local_frame_view = ToLocalFrameView(frame_view); + return local_frame_view->GetFrame().GetDocument(); + } + } + return nullptr; +} + } // namespace struct InspectorDOMSnapshotAgent::VectorStringHashTraits @@ -99,7 +117,8 @@ Response InspectorDOMSnapshotAgent::getSnapshot( std::unique_ptr<protocol::Array<String>> style_whitelist, - protocol::Maybe<bool> get_dom_listeners, + protocol::Maybe<bool> include_event_listeners, + protocol::Maybe<bool> include_paint_order, std::unique_ptr<protocol::Array<protocol::DOMSnapshot::DOMNode>>* dom_nodes, std::unique_ptr<protocol::Array<protocol::DOMSnapshot::LayoutTreeNode>>* layout_tree_nodes, @@ -129,8 +148,14 @@ std::make_pair(style_whitelist->get(i), property_id)); } + if (include_paint_order.fromMaybe(false)) { + paint_order_map_ = std::make_unique<PaintOrderMap>(); + next_paint_order_index_ = 0; + TraversePaintLayerTree(document); + } + // Actual traversal. - VisitNode(document, get_dom_listeners.fromMaybe(false)); + VisitNode(document, include_event_listeners.fromMaybe(false)); // Extract results from state and reset. *dom_nodes = std::move(dom_nodes_); @@ -138,16 +163,18 @@ *computed_styles = std::move(computed_styles_); computed_styles_map_.reset(); css_property_whitelist_.reset(); + paint_order_map_.reset(); return Response::OK(); } int InspectorDOMSnapshotAgent::VisitNode(Node* node, bool include_event_listeners) { - if (node->IsDocumentNode()) { - // Update layout tree before traversal of document so that we inspect a - // current and consistent state of all trees. + // Update layout tree before traversal of document so that we inspect a + // current and consistent state of all trees. No need to do this if paint + // order was calculated, since layout trees were already updated during + // TraversePaintLayerTree(). + if (node->IsDocumentNode() && !paint_order_map_) node->GetDocument().UpdateStyleAndLayoutTree(); - } String node_value; switch (node->getNodeType()) { @@ -363,6 +390,16 @@ if (style_index != -1) layout_tree_node->setStyleIndex(style_index); + if (paint_order_map_) { + PaintLayer* paint_layer = layout_object->EnclosingLayer(); + + // We visited all PaintLayers when building |paint_order_map_|. + DCHECK(paint_order_map_->Contains(paint_layer)); + + if (int paint_order = paint_order_map_->at(paint_layer)) + layout_tree_node->setPaintOrder(paint_order); + } + if (layout_object->IsText()) { LayoutText* layout_text = ToLayoutText(layout_object); layout_tree_node->setLayoutText(layout_text->GetText()); @@ -435,6 +472,41 @@ return index; } +void InspectorDOMSnapshotAgent::TraversePaintLayerTree(Document* document) { + // Update layout tree before traversal of document so that we inspect a + // current and consistent state of all trees. + document->UpdateStyleAndLayoutTree(); + + PaintLayer* root_layer = document->GetLayoutView()->Layer(); + // LayoutView requires a PaintLayer. + DCHECK(root_layer); + + VisitPaintLayer(root_layer); +} + +void InspectorDOMSnapshotAgent::VisitPaintLayer(PaintLayer* layer) { + DCHECK(!paint_order_map_->Contains(layer)); + + paint_order_map_->Set(layer, next_paint_order_index_); + next_paint_order_index_++; + + // If there is an embedded document, integrate it into the painting order. + Document* embedded_document = GetEmbeddedDocument(layer); + if (embedded_document) + TraversePaintLayerTree(embedded_document); + + // If there's an embedded document, there shouldn't be any children. + DCHECK(!embedded_document || !layer->FirstChild()); + + if (!embedded_document) { + PaintLayerStackingNode* node = layer->StackingNode(); + PaintLayerStackingNodeIterator iterator(*node, kAllChildren); + while (PaintLayerStackingNode* child_node = iterator.Next()) { + VisitPaintLayer(child_node->Layer()); + } + } +} + void InspectorDOMSnapshotAgent::Trace(blink::Visitor* visitor) { visitor->Trace(inspected_frames_); visitor->Trace(dom_debugger_agent_);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.h b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.h index 102f100..ae8ee5a 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMSnapshotAgent.h
@@ -14,9 +14,11 @@ namespace blink { +class Document; class Element; class InspectedFrames; class Node; +class PaintLayer; class CORE_EXPORT InspectorDOMSnapshotAgent final : public InspectorBaseAgent<protocol::DOMSnapshot::Metainfo> { @@ -32,7 +34,8 @@ protocol::Response getSnapshot( std::unique_ptr<protocol::Array<String>> style_whitelist, - protocol::Maybe<bool> get_dom_listeners, + protocol::Maybe<bool> include_event_listeners, + protocol::Maybe<bool> include_paint_order, std::unique_ptr<protocol::Array<protocol::DOMSnapshot::DOMNode>>* dom_nodes, std::unique_ptr<protocol::Array<protocol::DOMSnapshot::LayoutTreeNode>>* @@ -65,12 +68,17 @@ // styles in |style_whitelist_|. int GetStyleIndexForNode(Node*); + // Traverses the PaintLayer tree in paint order to fill |paint_order_map_|. + void TraversePaintLayerTree(Document*); + void VisitPaintLayer(PaintLayer*); + struct VectorStringHashTraits; using ComputedStylesMap = WTF::HashMap<Vector<String>, int, VectorStringHashTraits, VectorStringHashTraits>; using CSSPropertyWhitelist = Vector<std::pair<String, CSSPropertyID>>; + using PaintOrderMap = WTF::HashMap<PaintLayer*, int>; // State of current snapshot. std::unique_ptr<protocol::Array<protocol::DOMSnapshot::DOMNode>> dom_nodes_; @@ -83,6 +91,9 @@ std::unique_ptr<ComputedStylesMap> computed_styles_map_; std::unique_ptr<Vector<std::pair<String, CSSPropertyID>>> css_property_whitelist_; + // Maps a PaintLayer to its paint order index. + std::unique_ptr<PaintOrderMap> paint_order_map_; + int next_paint_order_index_ = 0; Member<InspectedFrames> inspected_frames_; Member<InspectorDOMDebuggerAgent> dom_debugger_agent_;
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json index 33c5b81..ab21ef8 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.json +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -4439,12 +4439,12 @@ }, { "name": "startCharacterIndex", - "description": "The starting index in characters, for this post layout textbox substring. Characters that would be represented as a surrogate pair in UTF-16 have length 2.", + "description": "The starting index in characters, for this post layout textbox substring. Characters that\nwould be represented as a surrogate pair in UTF-16 have length 2.", "type": "integer" }, { "name": "numCharacters", - "description": "The number of characters in this post layout textbox substring. Characters that would be represented as a surrogate pair in UTF-16 have length 2.", + "description": "The number of characters in this post layout textbox substring. Characters that would be\nrepresented as a surrogate pair in UTF-16 have length 2.", "type": "integer" } ] @@ -4484,6 +4484,12 @@ "description": "Index into the `computedStyles` array returned by `getSnapshot`.", "optional": true, "type": "integer" + }, + { + "name": "paintOrder", + "description": "Global paint order index, which is determined by the stacking order of the nodes. Nodes\nthat are painted together will have the same index. Only provided if includePaintOrder in\ngetSnapshot was true.", + "optional": true, + "type": "integer" } ] }, @@ -4538,6 +4544,12 @@ "description": "Whether or not to retrieve details of DOM listeners (default false).", "optional": true, "type": "boolean" + }, + { + "name": "includePaintOrder", + "description": "Whether to determine and include the paint order index of LayoutTreeNodes (default false).", + "optional": true, + "type": "boolean" } ], "returns": [
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.pdl b/third_party/WebKit/Source/core/inspector/browser_protocol.pdl index 0d3e6a03..4cddd342 100644 --- a/third_party/WebKit/Source/core/inspector/browser_protocol.pdl +++ b/third_party/WebKit/Source/core/inspector/browser_protocol.pdl
@@ -2031,9 +2031,11 @@ properties # The absolute position bounding box. DOM.Rect boundingBox - # The starting index in characters, for this post layout textbox substring. Characters that would be represented as a surrogate pair in UTF-16 have length 2. + # The starting index in characters, for this post layout textbox substring. Characters that + # would be represented as a surrogate pair in UTF-16 have length 2. integer startCharacterIndex - # The number of characters in this post layout textbox substring. Characters that would be represented as a surrogate pair in UTF-16 have length 2. + # The number of characters in this post layout textbox substring. Characters that would be + # represented as a surrogate pair in UTF-16 have length 2. integer numCharacters # Details of an element in the DOM tree with a LayoutObject. @@ -2049,6 +2051,10 @@ optional array of InlineTextBox inlineTextNodes # Index into the `computedStyles` array returned by `getSnapshot`. optional integer styleIndex + # Global paint order index, which is determined by the stacking order of the nodes. Nodes + # that are painted together will have the same index. Only provided if includePaintOrder in + # getSnapshot was true. + optional integer paintOrder # A subset of the full ComputedStyle as defined by the request whitelist. type ComputedStyle extends object @@ -2074,6 +2080,8 @@ array of string computedStyleWhitelist # Whether or not to retrieve details of DOM listeners (default false). optional boolean includeEventListeners + # Whether to determine and include the paint order index of LayoutTreeNodes (default false). + optional boolean includePaintOrder returns # The nodes in the DOM tree. The DOMNode at index 0 corresponds to the root document. array of DOMNode domNodes
diff --git a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp index 6622188..b7c24a4e 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObjectTest.cpp
@@ -9,6 +9,7 @@ #include "core/layout/LayoutTestHelper.h" #include "core/layout/LayoutTextFragment.h" #include "core/layout/LayoutView.h" +#include "core/svg/SVGGElement.h" #include "platform/json/JSONValues.h" #include "platform/testing/runtime_enabled_features_test_helpers.h" #include "testing/gmock/include/gmock/gmock.h" @@ -705,4 +706,22 @@ "\\u0440\\u043E\\u0434\\u0435\\u043D\\u0434\\u0435\\u043D\\n\"")); } +TEST_F(LayoutObjectTest, DisplayContentsSVGGElementInHTML) { + SetBodyInnerHTML(R"HTML( + <style>*|g { display:contents}</style> + <span id=span></span> + )HTML"); + + Element* span = GetDocument().getElementById("span"); + SVGGElement* svg_element = SVGGElement::Create(GetDocument()); + Text* text = Text::Create(GetDocument(), "text"); + svg_element->appendChild(text); + span->appendChild(svg_element); + + GetDocument().View()->UpdateAllLifecyclePhases(); + + ASSERT_FALSE(svg_element->GetLayoutObject()); + ASSERT_FALSE(text->GetLayoutObject()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc index 00be139..d4043b30 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -926,6 +926,10 @@ abort_when_bfc_resolved_ |= !layout_result->UnpositionedFloats().IsEmpty(); if (child_space->FloatsBfcOffset()) DCHECK(layout_result->UnpositionedFloats().IsEmpty()); + // If our BFC offset is unknown, and the child got pushed down by floats, so + // will we. + if (layout_result->IsPushedByFloats()) + container_builder_.SetIsPushedByFloats(); } // A child may have aborted its layout if it resolved its BFC offset. If @@ -1413,10 +1417,14 @@ } } - if (!has_processed_first_child_ && !is_pushed_by_floats) { + if (!has_processed_first_child_ && + (container_builder_.IsPushedByFloats() || !is_pushed_by_floats)) { // We're breaking before the first piece of in-flow content inside this // block, even if it's not a valid class C break point [1] in this case. We - // really don't want to break here, if we can find something better. + // really don't want to break here, if we can find something better. A class + // C break point occurs if a first child has been pushed by floats, but this + // only applies to the outermost block that gets pushed (in case this parent + // and the child have adjoining top margins). // // [1] https://www.w3.org/TR/css-break-3/#possible-breaks container_builder_.SetHasLastResortBreak(); @@ -1608,16 +1616,23 @@ } WritingMode writing_mode; + Optional<LayoutUnit> clearance_offset; + if (!constraint_space_.IsNewFormattingContext()) + clearance_offset = ConstraintSpace().ClearanceOffset(); if (child.IsInline()) { - space_builder.SetClearanceOffset(ConstraintSpace().ClearanceOffset()); writing_mode = Style().GetWritingMode(); } else { const ComputedStyle& child_style = child.Style(); - space_builder - .SetClearanceOffset( - exclusion_space_->ClearanceOffset(child_style.Clear())) - .SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style)) - .SetTextDirection(child_style.Direction()); + LayoutUnit child_clearance_offset = + exclusion_space_->ClearanceOffset(child_style.Clear()); + if (clearance_offset) { + clearance_offset = + std::max(clearance_offset.value(), child_clearance_offset); + } else { + clearance_offset = child_clearance_offset; + } + space_builder.SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style)); + space_builder.SetTextDirection(child_style.Direction()); writing_mode = child_style.GetWritingMode(); // PositionListMarker() requires a first line baseline. @@ -1629,6 +1644,7 @@ : kIdeographicBaseline}); } } + space_builder.SetClearanceOffset(clearance_offset); LayoutUnit space_available; if (ConstraintSpace().HasBlockFragmentation()) {
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc index 5289870..e2f0f4f 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc
@@ -2566,12 +2566,6 @@ } TEST_F(NGColumnLayoutAlgorithmTest, NoClassCBreakPointBeforeBfc) { - // TODO(mstensho): Get rid of #workaround below. It's needed because clearance - // is applied after layout, with no second layout pass. A second pass is - // really needed by fragmentation, since the amount of remaining space may - // have decreased so much that we need to break inside (while we didn't have - // to in the first pass). Ideally, we'd specify clear:both on #container - // instead, but that doesn't work currently. SetBodyInnerHTML(R"HTML( <style> #parent { @@ -2586,8 +2580,7 @@ <div id="parent"> <div style="width:50px; height:50px;"></div> <div style="float:left; width:100%; height:40px;"></div> - <div id="workaround" style="clear:both; width:1px;"></div> - <div id="container" style="width:55px;"> + <div id="container" style="clear:both; width:55px;"> <div style="display:flow-root; break-inside:avoid; width:44px; height:60px;"></div> </div> </div> @@ -2601,7 +2594,6 @@ offset:0,0 size:100x100 offset:0,0 size:50x50 offset:0,50 size:100x40 - offset:0,90 size:1x0 offset:110,0 size:100x60 offset:0,0 size:55x60 offset:0,0 size:44x60
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.h b/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.h index 59cddb2..b80bb9a 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_container_fragment_builder.h
@@ -117,6 +117,7 @@ is_pushed_by_floats_ = true; return *this; } + bool IsPushedByFloats() const { return is_pushed_by_floats_; } #ifndef NDEBUG String ToString() const;
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp index 0f6fbcf..bc8948d3 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.cpp
@@ -21,7 +21,6 @@ #include "core/layout/svg/SVGResources.h" #include "core/layout/svg/SVGResourcesCache.h" -#include "core/svg/SVGElementProxy.h" #include "core/svg/SVGResource.h" #include "core/svg/SVGTreeScopeResources.h" #include "platform/wtf/AutoReset.h" @@ -63,17 +62,6 @@ ClearInvalidationMask(); } -SVGElementProxySet* LayoutSVGResourceContainer::ElementProxySet() { - return GetElement()->ElementProxySet(); -} - -void LayoutSVGResourceContainer::NotifyContentChanged() { - if (LocalSVGResource* resource = ResourceForContainer(*this)) - resource->NotifyContentChanged(); - if (SVGElementProxySet* proxy_set = ElementProxySet()) - proxy_set->NotifyContentChanged(GetElement()->GetTreeScope()); -} - void LayoutSVGResourceContainer::WillBeDestroyed() { LayoutSVGHiddenContainer::WillBeDestroyed(); // The resource is being torn down. If we have any clients, move those to be @@ -117,9 +105,7 @@ if (is_invalidating_) return; LocalSVGResource* resource = ResourceForContainer(*this); - SVGElementProxySet* proxy_set = ElementProxySet(); - if (clients_.IsEmpty() && (!proxy_set || proxy_set->IsEmpty()) && - (!resource || !resource->HasClients())) + if (clients_.IsEmpty() && (!resource || !resource->HasClients())) return; // Remove modes for which invalidations have already been // performed. If no modes remain we are done. @@ -147,8 +133,9 @@ MarkForLayoutAndParentResourceInvalidation(*client, needs_layout); } - // Invalidate clients registered via an SVGElementProxy/SVGResource. - NotifyContentChanged(); + // Invalidate clients registered via an SVGResource. + if (resource) + resource->NotifyContentChanged(); is_invalidating_ = false; }
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h index ed3170a..4fcefdc7 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceContainer.h
@@ -25,7 +25,6 @@ namespace blink { class LocalSVGResource; -class SVGElementProxySet; enum LayoutSVGResourceType { kMaskerResourceType, @@ -93,9 +92,6 @@ // Used from RemoveAllClientsFromCache methods. void MarkAllClientsForInvalidation(InvalidationModeMask); - void NotifyContentChanged(); - SVGElementProxySet* ElementProxySet(); - void WillBeDestroyed() override; bool is_in_layout_;
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp index 914743c..996dd3884 100644 --- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp +++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceFilter.cpp
@@ -25,6 +25,7 @@ #include "core/svg/SVGFilterElement.h" #include "core/svg/SVGFilterPrimitiveStandardAttributes.h" +#include "core/svg/SVGResource.h" #include "core/svg/graphics/filters/SVGFilterBuilder.h" namespace blink { @@ -129,7 +130,9 @@ // Issue paint invalidations for the image on the screen. MarkClientForInvalidation(*filter.key, kPaintInvalidation); } - NotifyContentChanged(); + if (LocalSVGResource* resource = + ToSVGFilterElement(GetElement())->AssociatedResource()) + resource->NotifyContentChanged(); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp b/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp index f73be70..635b7be 100644 --- a/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp +++ b/third_party/WebKit/Source/core/paint/FilterEffectBuilder.cpp
@@ -28,9 +28,9 @@ #include <algorithm> #include "core/style/FilterOperations.h" -#include "core/svg/SVGElementProxy.h" #include "core/svg/SVGFilterElement.h" #include "core/svg/SVGLengthContext.h" +#include "core/svg/SVGResource.h" #include "core/svg/graphics/filters/SVGFilterBuilder.h" #include "platform/LengthFunctions.h" #include "platform/graphics/CompositorFilterOperations.h" @@ -124,19 +124,7 @@ float zoom, const PaintFlags* fill_flags, const PaintFlags* stroke_flags) - : FilterEffectBuilder(nullptr, - reference_box, - zoom, - fill_flags, - stroke_flags) {} - -FilterEffectBuilder::FilterEffectBuilder(Node* target, - const FloatRect& reference_box, - float zoom, - const PaintFlags* fill_flags, - const PaintFlags* stroke_flags) - : target_context_(target), - reference_box_(reference_box), + : reference_box_(reference_box), zoom_(zoom), fill_flags_(fill_flags), stroke_flags_(stroke_flags) {} @@ -420,10 +408,9 @@ Filter* FilterEffectBuilder::BuildReferenceFilter( const ReferenceFilterOperation& reference_operation, FilterEffect* previous_effect) const { - DCHECK(target_context_); - Element* filter_element = reference_operation.ElementProxy().FindElement( - target_context_->GetTreeScope()); - if (auto* filter = ToSVGFilterElementOrNull(filter_element)) + SVGResource* resource = reference_operation.Resource(); + if (auto* filter = + ToSVGFilterElementOrNull(resource ? resource->Target() : nullptr)) return BuildReferenceFilter(*filter, previous_effect); return nullptr; }
diff --git a/third_party/WebKit/Source/core/paint/FilterEffectBuilder.h b/third_party/WebKit/Source/core/paint/FilterEffectBuilder.h index 8349dfa..72aa4b8 100644 --- a/third_party/WebKit/Source/core/paint/FilterEffectBuilder.h +++ b/third_party/WebKit/Source/core/paint/FilterEffectBuilder.h
@@ -39,7 +39,6 @@ class FilterEffect; class FilterOperations; class FloatRect; -class Node; class ReferenceFilterOperation; class SVGFilterElement; class SVGFilterGraphNodeMap; @@ -52,11 +51,6 @@ float zoom, const PaintFlags* fill_flags = nullptr, const PaintFlags* stroke_flags = nullptr); - FilterEffectBuilder(Node*, - const FloatRect& reference_box, - float zoom, - const PaintFlags* fill_flags = nullptr, - const PaintFlags* stroke_flags = nullptr); Filter* BuildReferenceFilter(SVGFilterElement&, FilterEffect* previous_effect, @@ -71,7 +65,6 @@ Filter* BuildReferenceFilter(const ReferenceFilterOperation&, FilterEffect* previous_effect) const; - Member<Node> target_context_; FloatRect reference_box_; float zoom_; const PaintFlags* fill_flags_;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.cpp b/third_party/WebKit/Source/core/paint/PaintLayer.cpp index dc0c2f6..18f04390 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayer.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayer.cpp
@@ -189,7 +189,7 @@ if (rare_data_ && rare_data_->resource_info) { const ComputedStyle& style = GetLayoutObject().StyleRef(); if (style.HasFilter()) - style.Filter().RemoveClient(rare_data_->resource_info); + style.Filter().RemoveClient(*rare_data_->resource_info); if (IsReferenceClipPath(style.ClipPath())) { ToReferenceClipPathOperation(style.ClipPath()) ->RemoveClient(*rare_data_->resource_info); @@ -2908,15 +2908,10 @@ return; const bool had_resource_info = ResourceInfo(); - if (new_style.HasFilterInducingProperty()) { - new_style.Filter().AddClient(&EnsureResourceInfo(), - GetLayoutObject() - .GetDocument() - .GetTaskRunner(TaskType::kUnspecedLoading) - .get()); - } + if (new_style.HasFilterInducingProperty()) + new_style.Filter().AddClient(EnsureResourceInfo()); if (had_resource_info && old_style) - old_style->Filter().RemoveClient(ResourceInfo()); + old_style->Filter().RemoveClient(*ResourceInfo()); if (PaintLayerResourceInfo* resource_info = ResourceInfo()) resource_info->InvalidateFilterChain(); } @@ -3084,8 +3079,8 @@ reference_box == operations.ReferenceBox()) return; - operations = FilterEffectBuilder(EnclosingNode(), reference_box, zoom) - .BuildFilterOperations(filter); + operations = + FilterEffectBuilder(reference_box, zoom).BuildFilterOperations(filter); } CompositorFilterOperations @@ -3093,7 +3088,7 @@ const auto& style = GetLayoutObject().StyleRef(); float zoom = style.EffectiveZoom(); FloatRect reference_box = FilterReferenceBox(style.BackdropFilter(), zoom); - return FilterEffectBuilder(EnclosingNode(), reference_box, zoom) + return FilterEffectBuilder(reference_box, zoom) .BuildFilterOperations(style.BackdropFilter()); } @@ -3148,8 +3143,7 @@ const auto& style = GetLayoutObject().StyleRef(); float zoom = style.EffectiveZoom(); - FilterEffectBuilder builder(EnclosingNode(), - FilterReferenceBox(style.Filter(), zoom), zoom); + FilterEffectBuilder builder(FilterReferenceBox(style.Filter(), zoom), zoom); resource_info->SetLastEffect( builder.BuildFilterEffect(FilterOperationsIncludingReflection())); return resource_info->LastEffect();
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.cpp b/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.cpp index 07950084..44571167 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.cpp
@@ -41,12 +41,6 @@ DCHECK(!layer_); } -TreeScope* PaintLayerResourceInfo::GetTreeScope() { - DCHECK(layer_); - Node* node = layer_->GetLayoutObject().GetNode(); - return node ? &node->GetTreeScope() : nullptr; -} - void PaintLayerResourceInfo::ResourceContentChanged() { DCHECK(layer_); LayoutObject& layout_object = layer_->GetLayoutObject();
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.h b/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.h index cdda9f7..8f05371 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.h +++ b/third_party/WebKit/Source/core/paint/PaintLayerResourceInfo.h
@@ -63,8 +63,6 @@ void ClearLayer() { layer_ = nullptr; } - TreeScope* GetTreeScope() override; - void ResourceContentChanged() override; void ResourceElementChanged() override;
diff --git a/third_party/WebKit/Source/core/paint/SVGFilterPainter.cpp b/third_party/WebKit/Source/core/paint/SVGFilterPainter.cpp index 03509b1c..4719f6f 100644 --- a/third_party/WebKit/Source/core/paint/SVGFilterPainter.cpp +++ b/third_party/WebKit/Source/core/paint/SVGFilterPainter.cpp
@@ -99,7 +99,7 @@ } SVGFilterGraphNodeMap* node_map = SVGFilterGraphNodeMap::Create(); - FilterEffectBuilder builder(nullptr, object.ObjectBoundingBox(), 1); + FilterEffectBuilder builder(object.ObjectBoundingBox(), 1); Filter* filter = builder.BuildReferenceFilter( ToSVGFilterElement(*filter_.GetElement()), nullptr, node_map); if (!filter || !filter->LastEffect())
diff --git a/third_party/WebKit/Source/core/style/FilterOperation.cpp b/third_party/WebKit/Source/core/style/FilterOperation.cpp index 02cec41..eea10d30 100644 --- a/third_party/WebKit/Source/core/style/FilterOperation.cpp +++ b/third_party/WebKit/Source/core/style/FilterOperation.cpp
@@ -25,7 +25,7 @@ #include "core/style/FilterOperation.h" -#include "core/svg/SVGElementProxy.h" +#include "core/svg/SVGResource.h" #include "platform/LengthFunctions.h" #include "platform/animation/AnimationUtilities.h" #include "platform/graphics/filters/FEDropShadow.h" @@ -45,7 +45,7 @@ } void ReferenceFilterOperation::Trace(blink::Visitor* visitor) { - visitor->Trace(element_proxy_); + visitor->Trace(resource_); visitor->Trace(filter_); FilterOperation::Trace(visitor); } @@ -57,26 +57,25 @@ return last_effect->MapRect(rect); } -ReferenceFilterOperation::ReferenceFilterOperation( - const String& url, - SVGElementProxy& element_proxy) - : FilterOperation(REFERENCE), url_(url), element_proxy_(&element_proxy) {} +ReferenceFilterOperation::ReferenceFilterOperation(const String& url, + SVGResource* resource) + : FilterOperation(REFERENCE), url_(url), resource_(resource) {} -void ReferenceFilterOperation::AddClient( - SVGResourceClient* client, - base::SingleThreadTaskRunner* task_runner) { - element_proxy_->AddClient(client, task_runner); +void ReferenceFilterOperation::AddClient(SVGResourceClient& client) { + if (resource_) + resource_->AddClient(client); } -void ReferenceFilterOperation::RemoveClient(SVGResourceClient* client) { - element_proxy_->RemoveClient(client); +void ReferenceFilterOperation::RemoveClient(SVGResourceClient& client) { + if (resource_) + resource_->RemoveClient(client); } bool ReferenceFilterOperation::operator==(const FilterOperation& o) const { if (!IsSameType(o)) return false; const ReferenceFilterOperation& other = ToReferenceFilterOperation(o); - return url_ == other.url_ && element_proxy_ == other.element_proxy_; + return url_ == other.url_ && resource_ == other.resource_; } FilterOperation* BasicColorMatrixFilterOperation::Blend(
diff --git a/third_party/WebKit/Source/core/style/FilterOperation.h b/third_party/WebKit/Source/core/style/FilterOperation.h index 35c53a8..2b7fe6d 100644 --- a/third_party/WebKit/Source/core/style/FilterOperation.h +++ b/third_party/WebKit/Source/core/style/FilterOperation.h
@@ -27,7 +27,6 @@ #define FilterOperation_h #include "base/macros.h" -#include "base/single_thread_task_runner.h" #include "core/CoreExport.h" #include "core/style/ShadowData.h" #include "platform/Length.h" @@ -40,8 +39,8 @@ namespace blink { class Filter; +class SVGResource; class SVGResourceClient; -class SVGElementProxy; // CSS Filters @@ -132,8 +131,8 @@ class CORE_EXPORT ReferenceFilterOperation : public FilterOperation { public: static ReferenceFilterOperation* Create(const String& url, - SVGElementProxy& element_proxy) { - return new ReferenceFilterOperation(url, element_proxy); + SVGResource* resource) { + return new ReferenceFilterOperation(url, resource); } bool AffectsOpacity() const override { return true; } @@ -145,15 +144,15 @@ Filter* GetFilter() const { return filter_.Get(); } void SetFilter(Filter* filter) { filter_ = filter; } - SVGElementProxy& ElementProxy() const { return *element_proxy_; } + SVGResource* Resource() const { return resource_; } - void AddClient(SVGResourceClient*, base::SingleThreadTaskRunner*); - void RemoveClient(SVGResourceClient*); + void AddClient(SVGResourceClient&); + void RemoveClient(SVGResourceClient&); virtual void Trace(blink::Visitor*); private: - ReferenceFilterOperation(const String& url, SVGElementProxy&); + ReferenceFilterOperation(const String& url, SVGResource*); FilterOperation* Blend(const FilterOperation* from, double progress) const override { @@ -164,7 +163,7 @@ bool operator==(const FilterOperation&) const override; String url_; - Member<SVGElementProxy> element_proxy_; + Member<SVGResource> resource_; Member<Filter> filter_; };
diff --git a/third_party/WebKit/Source/core/style/FilterOperations.cpp b/third_party/WebKit/Source/core/style/FilterOperations.cpp index 32d137f..0a30d49 100644 --- a/third_party/WebKit/Source/core/style/FilterOperations.cpp +++ b/third_party/WebKit/Source/core/style/FilterOperations.cpp
@@ -104,16 +104,14 @@ return false; } -void FilterOperations::AddClient( - SVGResourceClient* client, - base::SingleThreadTaskRunner* task_runner) const { +void FilterOperations::AddClient(SVGResourceClient& client) const { for (FilterOperation* operation : operations_) { if (operation->GetType() == FilterOperation::REFERENCE) - ToReferenceFilterOperation(*operation).AddClient(client, task_runner); + ToReferenceFilterOperation(*operation).AddClient(client); } } -void FilterOperations::RemoveClient(SVGResourceClient* client) const { +void FilterOperations::RemoveClient(SVGResourceClient& client) const { for (FilterOperation* operation : operations_) { if (operation->GetType() == FilterOperation::REFERENCE) ToReferenceFilterOperation(*operation).RemoveClient(client);
diff --git a/third_party/WebKit/Source/core/style/FilterOperations.h b/third_party/WebKit/Source/core/style/FilterOperations.h index fdf0ca6..8adb5b0 100644 --- a/third_party/WebKit/Source/core/style/FilterOperations.h +++ b/third_party/WebKit/Source/core/style/FilterOperations.h
@@ -71,8 +71,8 @@ bool HasReferenceFilter() const; - void AddClient(SVGResourceClient*, base::SingleThreadTaskRunner*) const; - void RemoveClient(SVGResourceClient*) const; + void AddClient(SVGResourceClient&) const; + void RemoveClient(SVGResourceClient&) const; void Trace(blink::Visitor*);
diff --git a/third_party/WebKit/Source/core/svg/BUILD.gn b/third_party/WebKit/Source/core/svg/BUILD.gn index 749f9593..669bf38 100644 --- a/third_party/WebKit/Source/core/svg/BUILD.gn +++ b/third_party/WebKit/Source/core/svg/BUILD.gn
@@ -82,8 +82,6 @@ "SVGDocumentExtensions.h", "SVGElement.cpp", "SVGElement.h", - "SVGElementProxy.cpp", - "SVGElementProxy.h", "SVGElementRareData.cpp", "SVGElementRareData.h", "SVGEllipseElement.cpp",
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGElement.cpp index 82c83e1..dbbca123 100644 --- a/third_party/WebKit/Source/core/svg/SVGElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGElement.cpp
@@ -1244,13 +1244,6 @@ } #endif // DCHECK_IS_ON() -SVGElementProxySet* SVGElement::ElementProxySet() { - // Limit to specific element types. - if (!IsSVGFilterElement(*this) && !IsSVGClipPathElement(*this)) - return nullptr; - return &EnsureSVGRareData()->EnsureElementProxySet(); -} - SVGElementSet* SVGElement::SetOfIncomingReferences() const { if (!HasSVGRareData()) return nullptr;
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.h b/third_party/WebKit/Source/core/svg/SVGElement.h index 41f13787..10a1593 100644 --- a/third_party/WebKit/Source/core/svg/SVGElement.h +++ b/third_party/WebKit/Source/core/svg/SVGElement.h
@@ -40,7 +40,6 @@ class SubtreeLayoutScope; class SVGAnimatedString; class SVGElement; -class SVGElementProxySet; class SVGElementRareData; class SVGPropertyBase; class SVGSVGElement; @@ -171,8 +170,6 @@ bool InUseShadowTree() const; - SVGElementProxySet* ElementProxySet(); - void AddReferenceTo(SVGElement*); void NotifyIncomingReferences(bool needs_layout); void RebuildAllIncomingReferences();
diff --git a/third_party/WebKit/Source/core/svg/SVGElementProxy.cpp b/third_party/WebKit/Source/core/svg/SVGElementProxy.cpp deleted file mode 100644 index 14b8488..0000000 --- a/third_party/WebKit/Source/core/svg/SVGElementProxy.cpp +++ /dev/null
@@ -1,207 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "core/svg/SVGElementProxy.h" - -#include "core/dom/Document.h" -#include "core/dom/IdTargetObserver.h" -#include "core/svg/SVGElement.h" -#include "core/svg/SVGResourceClient.h" -#include "platform/loader/fetch/FetchParameters.h" -#include "platform/loader/fetch/ResourceFetcher.h" -#include "platform/loader/fetch/ResourceLoaderOptions.h" -#include "platform/loader/fetch/fetch_initiator_type_names.h" - -namespace blink { - -class SVGElementProxy::IdObserver : public IdTargetObserver { - public: - IdObserver(TreeScope& tree_scope, SVGElementProxy& proxy) - : IdTargetObserver(tree_scope.GetIdTargetObserverRegistry(), proxy.Id()), - tree_scope_(&tree_scope) {} - - void AddClient(SVGResourceClient* client) { clients_.insert(client); } - bool RemoveClient(SVGResourceClient* client) { - return clients_.erase(client); - } - bool HasClients() const { return !clients_.IsEmpty(); } - - TreeScope* GetTreeScope() const { return tree_scope_; } - void TransferClients(IdObserver& observer) { - for (const auto& client : clients_) - observer.clients_.insert(client.key, client.value); - clients_.clear(); - } - - virtual void Trace(blink::Visitor* visitor) { - visitor->Trace(clients_); - visitor->Trace(tree_scope_); - IdTargetObserver::Trace(visitor); - } - - void ContentChanged() { - DCHECK(Lifecycle().GetState() != DocumentLifecycle::kInPrePaint && - Lifecycle().GetState() != DocumentLifecycle::kInPaint); - HeapVector<Member<SVGResourceClient>> clients; - CopyToVector(clients_, clients); - for (SVGResourceClient* client : clients) - client->ResourceContentChanged(); - } - - private: - const DocumentLifecycle& Lifecycle() const { - return tree_scope_->GetDocument().Lifecycle(); - } - void IdTargetChanged() override { - DCHECK(Lifecycle().StateAllowsTreeMutations()); - HeapVector<Member<SVGResourceClient>> clients; - CopyToVector(clients_, clients); - for (SVGResourceClient* client : clients) - client->ResourceElementChanged(); - } - HeapHashCountedSet<Member<SVGResourceClient>> clients_; - Member<TreeScope> tree_scope_; -}; - -SVGElementProxy::SVGElementProxy(const AtomicString& id) - : id_(id), is_local_(true) {} - -SVGElementProxy::SVGElementProxy(const String& url, const AtomicString& id) - : id_(id), url_(url), is_local_(false) {} - -SVGElementProxy::~SVGElementProxy() = default; - -void SVGElementProxy::AddClient(SVGResourceClient* client, - base::SingleThreadTaskRunner* task_runner) { - // An empty id will never be a valid element reference. - if (id_.IsEmpty()) - return; - if (!is_local_) { - if (document_) { - DCHECK(!client->GetResource()); - client->SetResource(document_, task_runner); - } - return; - } - TreeScope* client_scope = client->GetTreeScope(); - if (!client_scope) - return; - // Ensure sure we have an observer registered for this tree scope. - auto& scope_observer = - observers_.insert(client_scope, nullptr).stored_value->value; - if (!scope_observer) - scope_observer = new IdObserver(*client_scope, *this); - - auto& observer = clients_.insert(client, nullptr).stored_value->value; - if (!observer) - observer = scope_observer; - - DCHECK(observer && scope_observer); - - // If the client moved to a different scope, we need to unregister the old - // observer and transfer any clients from it before replacing it. Thus any - // clients that remain to be removed will be transferred to the new observer, - // and hence removed from it instead. - if (observer != scope_observer) { - observer->Unregister(); - observer->TransferClients(*scope_observer); - observer = scope_observer; - } - observer->AddClient(client); -} - -void SVGElementProxy::RemoveClient(SVGResourceClient* client) { - // An empty id will never be a valid element reference. - if (id_.IsEmpty()) - return; - if (!is_local_) { - DCHECK_EQ(client->GetResource(), document_); - client->ClearResource(); - return; - } - auto entry = clients_.find(client); - if (entry == clients_.end()) - return; - IdObserver* observer = entry->value; - DCHECK(observer); - // If the client is not the last client in the scope, then no further action - // needs to be taken. - if (!observer->RemoveClient(client)) - return; - // Unregister and drop the scope association, then drop the client. - if (!observer->HasClients()) { - observer->Unregister(); - observers_.erase(observer->GetTreeScope()); - } - clients_.erase(entry); -} - -void SVGElementProxy::Resolve(Document& document) { - if (is_local_ || id_.IsEmpty() || url_.IsEmpty()) - return; - ResourceLoaderOptions options; - options.initiator_info.name = FetchInitiatorTypeNames::css; - FetchParameters params(ResourceRequest(url_), options); - document_ = - DocumentResource::FetchSVGDocument(params, document.Fetcher(), nullptr); - url_ = String(); -} - -TreeScope* SVGElementProxy::TreeScopeForLookup(TreeScope& tree_scope) const { - if (is_local_) - return &tree_scope; - if (!document_) - return nullptr; - return document_->GetDocument(); -} - -SVGElement* SVGElementProxy::FindElement(TreeScope& tree_scope) { - // An empty id will never be a valid element reference. - if (id_.IsEmpty()) - return nullptr; - TreeScope* lookup_scope = TreeScopeForLookup(tree_scope); - if (!lookup_scope) - return nullptr; - if (Element* target_element = lookup_scope->getElementById(id_)) { - SVGElementProxySet* proxy_set = - target_element->IsSVGElement() - ? ToSVGElement(target_element)->ElementProxySet() - : nullptr; - if (proxy_set) { - proxy_set->Add(*this); - return ToSVGElement(target_element); - } - } - return nullptr; -} - -void SVGElementProxy::ContentChanged(TreeScope& tree_scope) { - if (auto* observer = observers_.at(&tree_scope)) - observer->ContentChanged(); -} - -void SVGElementProxy::Trace(blink::Visitor* visitor) { - visitor->Trace(clients_); - visitor->Trace(observers_); - visitor->Trace(document_); -} - -void SVGElementProxySet::Add(SVGElementProxy& element_proxy) { - element_proxies_.insert(&element_proxy); -} - -bool SVGElementProxySet::IsEmpty() const { - return element_proxies_.IsEmpty(); -} - -void SVGElementProxySet::NotifyContentChanged(TreeScope& tree_scope) { - for (SVGElementProxy* proxy : element_proxies_) - proxy->ContentChanged(tree_scope); -} - -void SVGElementProxySet::Trace(blink::Visitor* visitor) { - visitor->Trace(element_proxies_); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGElementProxy.h b/third_party/WebKit/Source/core/svg/SVGElementProxy.h deleted file mode 100644 index 0e286a58..0000000 --- a/third_party/WebKit/Source/core/svg/SVGElementProxy.h +++ /dev/null
@@ -1,138 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SVGElementProxy_h -#define SVGElementProxy_h - -#include "core/loader/resource/DocumentResource.h" -#include "platform/heap/Handle.h" -#include "platform/wtf/text/AtomicString.h" -#include "platform/wtf/text/WTFString.h" - -namespace blink { - -class Document; -class SVGElement; -class SVGResourceClient; -class TreeScope; - -// A proxy to an SVGElement. Allows access to an element with a certain 'id', -// and provides its clients with notifications when the proxied element -// changes. -// -// SVGElements can be referenced using CSS, for example like: -// -// filter: url(#baz); -// -// or -// -// filter: url(foo.com/bar.svg#baz); -// -// SVGElementProxy provide a mechanism to persistently reference an SVGElement -// in such cases - regardless of if the proxied element reside in the same -// document (read: tree scope) or in an external (resource) document. Loading -// events related to external documents case needs be handled by the clients -// (SVGResourceClient's default implementation does this.) -// -// The proxy uses an 'id' (c.f getElementById) to determine which element to -// proxy. The id is looked up in the TreeScope provided by the client for a -// same-document reference and in the TreeScope of the Document for a external -// document reference. -// -// For same document references, the proxy will track changes that could affect -// the 'id' lookup, to handle elements being added, removed or having their -// 'id' mutated. (This does not apply for the external document case because -// it's assumed they will not mutate after load, due to scripts not being run -// etc.) -// -// SVGElementProxys are created by CSSURIValue, and have SVGResourceClients as -// a means to deliver change notifications. Clients that are interested in -// change notifications hence need to register a SVGResourceClient with the -// proxy. Most commonly this registration would take place when the -// ComputedStyle changes. -// -// Registration of a client does not establish a link to the proxied element -// right away. That is instead deferred until findElement(...) is called on the -// SVGElementProxy. At this point, the proxy will be registered with the -// element if the lookup is successful. (For external references lookups will -// not be registered, per the same assumption as mentioned above.) -// -// As content is mutated, clients will get notified via the proxied element -// which in turn will notify all registered proxies, which will notify all -// registered clients. -// -// <event> -> SVG...Element -> SVGElementProxy(0..N) -> SVGResourceClient(0..N) -// -class SVGElementProxy : public GarbageCollectedFinalized<SVGElementProxy> { - public: - // Create a proxy to an element in the same document. (See also - // SVGURLReferenceResolver and the definition of 'local url'.) - static SVGElementProxy* Create(const AtomicString& id) { - return new SVGElementProxy(id); - } - - // Create a proxy to an element in a different document (indicated by |url|.) - static SVGElementProxy* Create(const String& url, const AtomicString& id) { - return new SVGElementProxy(url, id); - } - virtual ~SVGElementProxy(); - - void AddClient(SVGResourceClient*, base::SingleThreadTaskRunner*); - void RemoveClient(SVGResourceClient*); - - // Resolve a potentially external document reference. - void Resolve(Document&); - - // Returns the proxied element, or null if the proxy is invalid. - SVGElement* FindElement(TreeScope&); - - // Notify the proxy that the structure of the subtree rooted at the proxied - // element has mutated. This should generally only be called via a proxy set. - void ContentChanged(TreeScope&); - - const AtomicString& Id() const { return id_; } - - virtual void Trace(blink::Visitor*); - - private: - explicit SVGElementProxy(const AtomicString&); - SVGElementProxy(const String&, const AtomicString&); - - TreeScope* TreeScopeForLookup(TreeScope&) const; - - class IdObserver; - - HeapHashMap<Member<SVGResourceClient>, Member<IdObserver>> clients_; - HeapHashMap<Member<TreeScope>, Member<IdObserver>> observers_; - Member<DocumentResource> document_; - AtomicString id_; - // URL for resolving references to external resource documents. Contains an - // absolute URL to the resource to load. Cleared when a load has been - // initiated. Ignored if m_isLocal is true. - String url_; - bool is_local_; -}; - -// Collection of SVGElementProxys. This is hosted by elements that can be -// subject to proxies (see SVGElement::elementProxySet), and is mainly a helper -// for dealing with the many-to-one structure of SVGElementProxy. -class SVGElementProxySet : public GarbageCollected<SVGElementProxySet> { - public: - void Add(SVGElementProxy&); - bool IsEmpty() const; - - // Notify proxy clients that the (content of the) proxied element has - // changed. - void NotifyContentChanged(TreeScope&); - - void Trace(blink::Visitor*); - - private: - using ProxySet = HeapHashSet<WeakMember<SVGElementProxy>>; - ProxySet element_proxies_; -}; - -} // namespace blink - -#endif // SVGElementProxy_h
diff --git a/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp b/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp index 730147f6..53a70fe 100644 --- a/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp +++ b/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp
@@ -6,7 +6,6 @@ #include "core/css/resolver/StyleResolver.h" #include "core/dom/Document.h" -#include "core/svg/SVGElementProxy.h" namespace blink { @@ -41,7 +40,6 @@ void SVGElementRareData::Trace(blink::Visitor* visitor) { visitor->Trace(outgoing_references_); visitor->Trace(incoming_references_); - visitor->Trace(element_proxy_set_); visitor->Trace(animated_smil_style_properties_); visitor->Trace(element_instances_); visitor->Trace(corresponding_element_); @@ -51,10 +49,4 @@ return &animate_motion_transform_; } -SVGElementProxySet& SVGElementRareData::EnsureElementProxySet() { - if (!element_proxy_set_) - element_proxy_set_ = new SVGElementProxySet; - return *element_proxy_set_; -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGElementRareData.h b/third_party/WebKit/Source/core/svg/SVGElementRareData.h index 967308b..060100b 100644 --- a/third_party/WebKit/Source/core/svg/SVGElementRareData.h +++ b/third_party/WebKit/Source/core/svg/SVGElementRareData.h
@@ -29,8 +29,6 @@ namespace blink { -class SVGElementProxySet; - class SVGElementRareData : public GarbageCollectedFinalized<SVGElementRareData> { public: @@ -50,8 +48,6 @@ return incoming_references_; } - SVGElementProxySet& EnsureElementProxySet(); - HeapHashSet<WeakMember<SVGElement>>& ElementInstances() { return element_instances_; } @@ -105,7 +101,6 @@ SVGElementSet outgoing_references_; SVGElementSet incoming_references_; HeapHashSet<WeakMember<SVGElement>> element_instances_; - Member<SVGElementProxySet> element_proxy_set_; Member<SVGElement> corresponding_element_; bool instances_updates_blocked_ : 1; bool use_override_computed_style_ : 1;
diff --git a/third_party/WebKit/Source/core/svg/SVGFilterElement.cpp b/third_party/WebKit/Source/core/svg/SVGFilterElement.cpp index edc4439..85dfcda8 100644 --- a/third_party/WebKit/Source/core/svg/SVGFilterElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGFilterElement.cpp
@@ -24,7 +24,8 @@ #include "core/svg/SVGFilterElement.h" #include "core/layout/svg/LayoutSVGResourceFilter.h" -#include "core/svg/SVGElementProxy.h" +#include "core/svg/SVGResource.h" +#include "core/svg/SVGTreeScopeResources.h" namespace blink { @@ -103,22 +104,27 @@ SVGElement::SvgAttributeChanged(attr_name); } +LocalSVGResource* SVGFilterElement::AssociatedResource() const { + return GetTreeScope().EnsureSVGTreeScopedResources().ExistingResourceForId( + GetIdAttribute()); +} + void SVGFilterElement::PrimitiveAttributeChanged( SVGFilterPrimitiveStandardAttributes& primitive, const QualifiedName& attribute) { if (LayoutObject* layout_object = GetLayoutObject()) { ToLayoutSVGResourceFilter(layout_object) ->PrimitiveAttributeChanged(primitive, attribute); - } else if (SVGElementProxySet* proxy_set = ElementProxySet()) { - proxy_set->NotifyContentChanged(GetTreeScope()); + } else if (LocalSVGResource* resource = AssociatedResource()) { + resource->NotifyContentChanged(); } } void SVGFilterElement::InvalidateFilterChain() { if (LayoutObject* layout_object = GetLayoutObject()) ToLayoutSVGResourceFilter(layout_object)->RemoveAllClientsFromCache(); - else if (SVGElementProxySet* proxy_set = ElementProxySet()) - proxy_set->NotifyContentChanged(GetTreeScope()); + else if (LocalSVGResource* resource = AssociatedResource()) + resource->NotifyContentChanged(); } void SVGFilterElement::ChildrenChanged(const ChildrenChange& change) {
diff --git a/third_party/WebKit/Source/core/svg/SVGFilterElement.h b/third_party/WebKit/Source/core/svg/SVGFilterElement.h index c2e7f2b2..23c9a04 100644 --- a/third_party/WebKit/Source/core/svg/SVGFilterElement.h +++ b/third_party/WebKit/Source/core/svg/SVGFilterElement.h
@@ -34,6 +34,7 @@ namespace blink { class SVGFilterPrimitiveStandardAttributes; +class LocalSVGResource; class CORE_EXPORT SVGFilterElement final : public SVGElement, public SVGURIReference { @@ -64,6 +65,9 @@ // Invalidate the entire filter chain. void InvalidateFilterChain(); + // Get the associated SVGResource object, if any. + LocalSVGResource* AssociatedResource() const; + private: explicit SVGFilterElement(Document&);
diff --git a/third_party/WebKit/Source/core/svg/SVGGElement.h b/third_party/WebKit/Source/core/svg/SVGGElement.h index c56302d..3b21d53 100644 --- a/third_party/WebKit/Source/core/svg/SVGGElement.h +++ b/third_party/WebKit/Source/core/svg/SVGGElement.h
@@ -25,7 +25,7 @@ namespace blink { -class SVGGElement final : public SVGGraphicsElement { +class CORE_EXPORT SVGGElement final : public SVGGraphicsElement { DEFINE_WRAPPERTYPEINFO(); public:
diff --git a/third_party/WebKit/Source/core/svg/SVGResource.cpp b/third_party/WebKit/Source/core/svg/SVGResource.cpp index 966036b..95b186d 100644 --- a/third_party/WebKit/Source/core/svg/SVGResource.cpp +++ b/third_party/WebKit/Source/core/svg/SVGResource.cpp
@@ -4,15 +4,21 @@ #include "core/svg/SVGResource.h" +#include "core/dom/Document.h" #include "core/dom/Element.h" #include "core/dom/IdTargetObserver.h" #include "core/dom/TreeScope.h" #include "core/layout/svg/LayoutSVGResourceContainer.h" #include "core/layout/svg/SVGResources.h" #include "core/layout/svg/SVGResourcesCache.h" +#include "core/loader/resource/DocumentResource.h" #include "core/svg/SVGElement.h" #include "core/svg/SVGResourceClient.h" #include "core/svg/SVGURIReference.h" +#include "platform/loader/fetch/FetchParameters.h" +#include "platform/loader/fetch/ResourceFetcher.h" +#include "platform/loader/fetch/ResourceLoaderOptions.h" +#include "platform/loader/fetch/fetch_initiator_type_names.h" namespace blink { @@ -33,6 +39,14 @@ clients_.erase(&client); } +void SVGResource::NotifyElementChanged() { + HeapVector<Member<SVGResourceClient>> clients; + CopyToVector(clients_, clients); + + for (SVGResourceClient* client : clients) + client->ResourceElementChanged(); +} + LayoutSVGResourceContainer* SVGResource::ResourceContainer() const { if (!target_) return nullptr; @@ -88,14 +102,6 @@ client->ResourceContentChanged(); } -void LocalSVGResource::NotifyElementChanged() { - HeapVector<Member<SVGResourceClient>> clients; - CopyToVector(clients_, clients); - - for (SVGResourceClient* client : clients) - client->ResourceElementChanged(); -} - void LocalSVGResource::TargetChanged(const AtomicString& id) { Element* new_target = tree_scope_->getElementById(id); if (new_target == target_) @@ -116,4 +122,47 @@ SVGResource::Trace(visitor); } +ExternalSVGResource::ExternalSVGResource(const KURL& url) : url_(url) {} + +void ExternalSVGResource::Load(const Document& document) { + if (resource_document_) + return; + ResourceLoaderOptions options; + options.initiator_info.name = FetchInitiatorTypeNames::css; + FetchParameters params(ResourceRequest(url_), options); + resource_document_ = + DocumentResource::FetchSVGDocument(params, document.Fetcher(), this); + target_ = ResolveTarget(); +} + +void ExternalSVGResource::NotifyFinished(Resource*) { + Element* new_target = ResolveTarget(); + if (new_target == target_) + return; + target_ = new_target; + NotifyElementChanged(); +} + +String ExternalSVGResource::DebugName() const { + return "ExternalSVGResource"; +} + +Element* ExternalSVGResource::ResolveTarget() { + if (!resource_document_) + return nullptr; + if (!url_.HasFragmentIdentifier()) + return nullptr; + Document* external_document = resource_document_->GetDocument(); + if (!external_document) + return nullptr; + return external_document->getElementById( + AtomicString(url_.FragmentIdentifier())); +} + +void ExternalSVGResource::Trace(Visitor* visitor) { + visitor->Trace(resource_document_); + SVGResource::Trace(visitor); + ResourceClient::Trace(visitor); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGResource.h b/third_party/WebKit/Source/core/svg/SVGResource.h index 95fbcdd..a4d4d35 100644 --- a/third_party/WebKit/Source/core/svg/SVGResource.h +++ b/third_party/WebKit/Source/core/svg/SVGResource.h
@@ -7,11 +7,16 @@ #include "base/macros.h" #include "platform/heap/Handle.h" +#include "platform/loader/fetch/ResourceClient.h" +#include "platform/weborigin/KURL.h" #include "platform/wtf/HashCountedSet.h" #include "platform/wtf/HashSet.h" +#include "platform/wtf/text/AtomicString.h" namespace blink { +class Document; +class DocumentResource; class Element; class IdTargetObserver; class LayoutSVGResourceContainer; @@ -21,10 +26,46 @@ // A class tracking a reference to an SVG resource (an element that constitutes // a paint server, mask, clip-path, filter et.c.) +// +// Elements can be referenced using CSS, for example like: +// +// filter: url(#baz); ("local") +// +// or +// +// filter: url(foo.com/bar.svg#baz); ("external") +// +// SVGResource provide a mechanism to persistently reference an element in such +// cases - regardless of if the element reside in the same document (read: tree +// scope) or in an external (resource) document. Loading events related to the +// external documents case are handled by the SVGResource. +// +// For same document references, changes that could affect the 'id' lookup will +// be tracked, to handle elements being added, removed or having their 'id' +// mutated. (This does not apply for the external document case because it's +// assumed they will not mutate after load, due to scripts not being run etc.) +// +// SVGResources are created, and managed, either by SVGTreeScopeResources +// (local) or CSSURIValue (external), and have SVGResourceClients as a means to +// deliver change notifications. Clients that are interested in change +// notifications hence need to register a SVGResourceClient with the +// SVGResource. Most commonly this registration would take place when the +// computed style changes. +// +// The element is bound either when the SVGResource is created (for local +// resources) or after the referenced resource has completed loading (for +// external resources.) +// +// As content is mutated, clients will get notified via the SVGResource. +// +// <event> -> SVG...Element -> SVGResource -> SVGResourceClient(0..N) +// class SVGResource : public GarbageCollectedFinalized<SVGResource> { public: virtual ~SVGResource(); + virtual void Load(const Document&) {} + Element* Target() const { return target_; } LayoutSVGResourceContainer* ResourceContainer() const; @@ -38,6 +79,8 @@ protected: SVGResource(); + void NotifyElementChanged(); + Member<Element> target_; HeapHashCountedSet<Member<SVGResourceClient>> clients_; @@ -64,13 +107,34 @@ private: void TargetChanged(const AtomicString& id); - void NotifyElementChanged(); Member<TreeScope> tree_scope_; Member<IdTargetObserver> id_observer_; HeapHashSet<Member<SVGElement>> pending_clients_; }; +// External resource reference (see SVGResource.) +class ExternalSVGResource final : public SVGResource, private ResourceClient { + USING_GARBAGE_COLLECTED_MIXIN(ExternalSVGResource); + + public: + explicit ExternalSVGResource(const KURL&); + + void Load(const Document&) override; + + void Trace(Visitor*) override; + + private: + Element* ResolveTarget(); + + // ResourceClient implementation + String DebugName() const override; + void NotifyFinished(Resource*) override; + + KURL url_; + Member<DocumentResource> resource_document_; +}; + } // namespace blink #endif // SVGResource_h
diff --git a/third_party/WebKit/Source/core/svg/SVGResourceClient.h b/third_party/WebKit/Source/core/svg/SVGResourceClient.h index a2e6be1..81e938aa 100644 --- a/third_party/WebKit/Source/core/svg/SVGResourceClient.h +++ b/third_party/WebKit/Source/core/svg/SVGResourceClient.h
@@ -6,27 +6,19 @@ #define SVGResourceClient_h #include "core/CoreExport.h" -#include "core/loader/resource/DocumentResource.h" #include "platform/heap/Handle.h" namespace blink { -class TreeScope; - -class CORE_EXPORT SVGResourceClient : public ResourceClient { +class CORE_EXPORT SVGResourceClient : public GarbageCollectedMixin { public: virtual ~SVGResourceClient() = default; - virtual TreeScope* GetTreeScope() = 0; - virtual void ResourceContentChanged() = 0; virtual void ResourceElementChanged() = 0; protected: SVGResourceClient() = default; - - String DebugName() const override { return "SVGResourceClient"; } - void NotifyFinished(Resource*) override { ResourceElementChanged(); } }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp index 5b05957a..23157ec 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
@@ -873,17 +873,11 @@ return nullptr; } -bool AXObject::DispatchEventToAOMEventListeners(Event& event, - Element* target_element) { +bool AXObject::DispatchEventToAOMEventListeners(Event& event) { HeapVector<Member<AccessibleNode>> event_path; for (AXObject* ancestor = this; ancestor; ancestor = ancestor->ParentObject()) { - Element* ancestor_element = ancestor->GetElement(); - if (!ancestor_element) - continue; - - AccessibleNode* ancestor_accessible_node = - ancestor_element->ExistingAccessibleNode(); + AccessibleNode* ancestor_accessible_node = ancestor->GetAccessibleNode(); if (!ancestor_accessible_node) continue; @@ -916,13 +910,13 @@ // AccessibleNode for the target element and create it if necessary - // otherwise we wouldn't be able to set the event target. However note // that if it didn't previously exist it won't be part of the event path. - if (!target_element) - target_element = GetElement(); - AccessibleNode* target = nullptr; - if (target_element) { - target = target_element->accessibleNode(); - event.SetTarget(target); + AccessibleNode* target = GetAccessibleNode(); + if (!target) { + Element* element = GetElement(); + if (element) + target = element->accessibleNode(); } + event.SetTarget(target); // Capturing phase. event.SetEventPhase(Event::kCapturingPhase); @@ -1133,6 +1127,7 @@ return IsSubWidget(RoleValue()) && Restriction() != kDisabled; } +// static bool AXObject::IsSubWidget(AccessibilityRole role) { switch (role) { case kCellRole: @@ -1640,9 +1635,8 @@ int child_count = siblings.size(); for (int index = 0; index < child_count; ++index) { - if (siblings[index].Get() == this) { + if (siblings[index].Get() == this) return index; - } } return 0; } @@ -2263,24 +2257,17 @@ // bool AXObject::RequestDecrementAction() { - Element* element = GetElement(); - if (element) { - Event* event = Event::CreateCancelable(EventTypeNames::accessibledecrement); - if (DispatchEventToAOMEventListeners(*event, element)) { - return true; - } - } + Event* event = Event::CreateCancelable(EventTypeNames::accessibledecrement); + if (DispatchEventToAOMEventListeners(*event)) + return true; return OnNativeDecrementAction(); } bool AXObject::RequestClickAction() { - Element* element = GetElement(); - if (element) { - Event* event = Event::CreateCancelable(EventTypeNames::accessibleclick); - if (DispatchEventToAOMEventListeners(*event, element)) - return true; - } + Event* event = Event::CreateCancelable(EventTypeNames::accessibleclick); + if (DispatchEventToAOMEventListeners(*event)) + return true; return OnNativeClickAction(); } @@ -2310,23 +2297,17 @@ } bool AXObject::RequestFocusAction() { - Element* element = GetElement(); - if (element) { - Event* event = Event::CreateCancelable(EventTypeNames::accessiblefocus); - if (DispatchEventToAOMEventListeners(*event, element)) - return true; - } + Event* event = Event::CreateCancelable(EventTypeNames::accessiblefocus); + if (DispatchEventToAOMEventListeners(*event)) + return true; return OnNativeFocusAction(); } bool AXObject::RequestIncrementAction() { - Element* element = GetElement(); - if (element) { - Event* event = Event::CreateCancelable(EventTypeNames::accessibleincrement); - if (DispatchEventToAOMEventListeners(*event, element)) - return true; - } + Event* event = Event::CreateCancelable(EventTypeNames::accessibleincrement); + if (DispatchEventToAOMEventListeners(*event)) + return true; return OnNativeIncrementAction(); } @@ -2336,13 +2317,10 @@ } bool AXObject::RequestScrollToMakeVisibleAction() { - Element* element = GetElement(); - if (element) { - Event* event = - Event::CreateCancelable(EventTypeNames::accessiblescrollintoview); - if (DispatchEventToAOMEventListeners(*event, element)) - return true; - } + Event* event = + Event::CreateCancelable(EventTypeNames::accessiblescrollintoview); + if (DispatchEventToAOMEventListeners(*event)) + return true; return OnNativeScrollToMakeVisibleAction(); } @@ -2369,13 +2347,9 @@ } bool AXObject::RequestShowContextMenuAction() { - Element* element = GetElement(); - if (element) { - Event* event = - Event::CreateCancelable(EventTypeNames::accessiblecontextmenu); - if (DispatchEventToAOMEventListeners(*event, element)) - return true; - } + Event* event = Event::CreateCancelable(EventTypeNames::accessiblecontextmenu); + if (DispatchEventToAOMEventListeners(*event)) + return true; return OnNativeShowContextMenuAction(); } @@ -2526,11 +2500,13 @@ return line_count; } +// static bool AXObject::IsARIAControl(AccessibilityRole aria_role) { return IsARIAInput(aria_role) || aria_role == kButtonRole || aria_role == kComboBoxMenuButtonRole || aria_role == kSliderRole; } +// static bool AXObject::IsARIAInput(AccessibilityRole aria_role) { return aria_role == kRadioButtonRole || aria_role == kCheckBoxRole || aria_role == kTextFieldRole || aria_role == kSwitchRole || @@ -2757,12 +2733,14 @@ return kButtonRole; } +// static const AtomicString& AXObject::RoleName(AccessibilityRole role) { static const Vector<AtomicString>* role_name_vector = CreateRoleNameVector(); return role_name_vector->at(role); } +// static const AtomicString& AXObject::InternalRoleName(AccessibilityRole role) { static const Vector<AtomicString>* internal_role_name_vector = CreateInternalRoleNameVector(); @@ -2770,10 +2748,102 @@ return internal_role_name_vector->at(role); } +// static +const AXObject* AXObject::LowestCommonAncestor(const AXObject& first, + const AXObject& second, + int* index_in_ancestor1, + int* index_in_ancestor2) { + *index_in_ancestor1 = -1; + *index_in_ancestor2 = -1; + + if (first.IsDetached() || second.IsDetached()) + return nullptr; + + if (first == second) + return &first; + + HeapVector<Member<const AXObject>> ancestors1; + ancestors1.push_back(&first); + while (ancestors1.back()) + ancestors1.push_back(ancestors1.back()->ParentObjectUnignored()); + + HeapVector<Member<const AXObject>> ancestors2; + ancestors2.push_back(&second); + while (ancestors2.back()) + ancestors2.push_back(ancestors2.back()->ParentObjectUnignored()); + + const AXObject* common_ancestor = nullptr; + while (!ancestors1.IsEmpty() && !ancestors2.IsEmpty() && + ancestors1.back() == ancestors2.back()) { + common_ancestor = ancestors1.back(); + ancestors1.pop_back(); + ancestors2.pop_back(); + } + + if (common_ancestor) { + if (!ancestors1.IsEmpty()) + *index_in_ancestor1 = ancestors1.back()->IndexInParent(); + if (!ancestors2.IsEmpty()) + *index_in_ancestor2 = ancestors2.back()->IndexInParent(); + } + + return common_ancestor; +} + VisiblePosition AXObject::VisiblePositionForIndex(int) const { return VisiblePosition(); } +bool operator==(const AXObject& first, const AXObject& second) { + if (first.IsDetached() || second.IsDetached()) + return false; + if (&first == &second) { + DCHECK_EQ(first.AXObjectID(), second.AXObjectID()); + return true; + } + return false; +} + +bool operator!=(const AXObject& first, const AXObject& second) { + return !(first == second); +} + +bool operator<(const AXObject& first, const AXObject& second) { + if (first.IsDetached() || second.IsDetached()) + return false; + + int index_in_ancestor1, index_in_ancestor2; + const AXObject* ancestor = AXObject::LowestCommonAncestor( + first, second, &index_in_ancestor1, &index_in_ancestor2); + DCHECK_GE(index_in_ancestor1, -1); + DCHECK_GE(index_in_ancestor2, -1); + if (!ancestor) + return false; + return index_in_ancestor1 < index_in_ancestor2; +} + +bool operator<=(const AXObject& first, const AXObject& second) { + return first == second || first < second; +} + +bool operator>(const AXObject& first, const AXObject& second) { + if (first.IsDetached() || second.IsDetached()) + return false; + + int index_in_ancestor1, index_in_ancestor2; + const AXObject* ancestor = AXObject::LowestCommonAncestor( + first, second, &index_in_ancestor1, &index_in_ancestor2); + DCHECK_GE(index_in_ancestor1, -1); + DCHECK_GE(index_in_ancestor2, -1); + if (!ancestor) + return false; + return index_in_ancestor1 > index_in_ancestor2; +} + +bool operator>=(const AXObject& first, const AXObject& second) { + return first == second || first > second; +} + std::ostream& operator<<(std::ostream& stream, const AXObject& obj) { return stream << AXObject::InternalRoleName(obj.RoleValue()) << ": " << obj.ComputedName();
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.h b/third_party/WebKit/Source/modules/accessibility/AXObject.h index 8dc2266..c2d90dc 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObject.h +++ b/third_party/WebKit/Source/modules/accessibility/AXObject.h
@@ -766,7 +766,7 @@ // Static helper functions. static bool IsARIAControl(AccessibilityRole); static bool IsARIAInput(AccessibilityRole); - // Is this a widget that requires container widget + // Is this a widget that requires container widget. static bool IsSubWidget(AccessibilityRole); static AccessibilityRole AriaRoleToWebCoreRole(const String&); static const AtomicString& RoleName(AccessibilityRole); @@ -774,6 +774,15 @@ static void AccessibleNodeListToElementVector(const AccessibleNodeList&, HeapVector<Member<Element>>&); + // Given two AX objects, returns the lowest common ancestor and the child + // indices in that ancestor corresponding to the branch under which each + // object is to be found. If the lowest common ancestor is the same as either + // of the objects, the corresponding index is set to -1 to indicate this. + static const AXObject* LowestCommonAncestor(const AXObject& first, + const AXObject& second, + int* index_in_ancestor1, + int* index_in_ancestor2); + protected: AXID id_; AXObjectVector children_; @@ -828,7 +837,7 @@ const AXObject* InertRoot() const; // Returns true if the event was handled. - bool DispatchEventToAOMEventListeners(Event&, Element*); + bool DispatchEventToAOMEventListeners(Event&); mutable Member<AXObject> parent_; @@ -866,6 +875,12 @@ DISALLOW_COPY_AND_ASSIGN(AXObject); }; +MODULES_EXPORT bool operator==(const AXObject& first, const AXObject& second); +MODULES_EXPORT bool operator!=(const AXObject& first, const AXObject& second); +MODULES_EXPORT bool operator<(const AXObject& first, const AXObject& second); +MODULES_EXPORT bool operator<=(const AXObject& first, const AXObject& second); +MODULES_EXPORT bool operator>(const AXObject& first, const AXObject& second); +MODULES_EXPORT bool operator>=(const AXObject& first, const AXObject& second); MODULES_EXPORT std::ostream& operator<<(std::ostream&, const AXObject&); #define DEFINE_AX_OBJECT_TYPE_CASTS(thisType, predicate) \
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp b/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp index c4701f5..911b73f 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXObjectTest.cpp
@@ -78,4 +78,46 @@ br->PreviousSibling()->RoleValue()); } +TEST_F(AccessibilityTest, ComparisonOperators) { + SetBodyInnerHTML(R"HTML(<input id='input' type='text' value='value'>" + R"<p id='paragraph'>hello<br id='br'>there</p>" + R"<button id='button'>button</button>)HTML"); + + const AXObject* root = GetAXRootObject(); + ASSERT_NE(nullptr, root); + const AXObject* input = GetAXObjectByElementId("input"); + ASSERT_NE(nullptr, input); + const AXObject* paragraph = GetAXObjectByElementId("paragraph"); + ASSERT_NE(nullptr, paragraph); + const AXObject* br = GetAXObjectByElementId("br"); + ASSERT_NE(nullptr, br); + const AXObject* button = GetAXObjectByElementId("button"); + ASSERT_NE(nullptr, button); + + EXPECT_TRUE(*root == *root); + EXPECT_FALSE(*root != *root); + EXPECT_FALSE(*root < *root); + EXPECT_TRUE(*root <= *root); + EXPECT_FALSE(*root > *root); + EXPECT_TRUE(*root >= *root); + + EXPECT_TRUE(*input > *root); + EXPECT_TRUE(*input >= *root); + EXPECT_FALSE(*input < *root); + EXPECT_FALSE(*input <= *root); + + EXPECT_TRUE(*input != *root); + EXPECT_TRUE(*input < *paragraph); + EXPECT_TRUE(*br > *input); + EXPECT_TRUE(*paragraph < *br); + EXPECT_TRUE(*br >= *paragraph); + + EXPECT_TRUE(*paragraph < *button); + EXPECT_TRUE(*button > *br); + EXPECT_FALSE(*button < *button); + EXPECT_TRUE(*button <= *button); + EXPECT_TRUE(*button >= *button); + EXPECT_FALSE(*button > *button); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/modules/accessibility/testing/AccessibilityTest.cpp b/third_party/WebKit/Source/modules/accessibility/testing/AccessibilityTest.cpp index ed23b7d..69885bd 100644 --- a/third_party/WebKit/Source/modules/accessibility/testing/AccessibilityTest.cpp +++ b/third_party/WebKit/Source/modules/accessibility/testing/AccessibilityTest.cpp
@@ -61,10 +61,9 @@ stream << std::string(level * 2, '+'); stream << *root << std::endl; - for (const auto child : const_cast<AXObject*>(root)->Children()) { + for (const Member<AXObject> child : root->Children()) { DCHECK(child); PrintAXTreeHelper(stream, child.Get(), level + 1); - stream << std::endl; } return stream; }
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp index 92ad1a0..b7ec51d 100644 --- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp
@@ -580,21 +580,15 @@ PruneLocalFontCache(0); } -TreeScope* CanvasRenderingContext2D::GetTreeScope() { - return &canvas()->GetTreeScope(); -} - void CanvasRenderingContext2D::ClearFilterReferences() { - filter_operations_.RemoveClient(this); + filter_operations_.RemoveClient(*this); filter_operations_.clear(); } void CanvasRenderingContext2D::UpdateFilterReferences( const FilterOperations& filters) { ClearFilterReferences(); - filters.AddClient( - this, - canvas()->GetDocument().GetTaskRunner(TaskType::kUnspecedLoading).get()); + filters.AddClient(*this); filter_operations_ = filters; }
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h index 31ffaa7e..f329a03 100644 --- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h +++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h
@@ -150,7 +150,6 @@ String GetIdFromControl(const Element*) override; // SVGResourceClient implementation - TreeScope* GetTreeScope() override; void ResourceContentChanged() override; void ResourceElementChanged() override;
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DState.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DState.cpp index 3b6fdfd1..f2f1cf1 100644 --- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DState.cpp +++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DState.cpp
@@ -352,7 +352,6 @@ stroke_flags_for_filter.setColor(stroke_style_->PaintColor()); FilterEffectBuilder filter_effect_builder( - style_resolution_host, FloatRect((FloatPoint()), FloatSize(canvas_size)), 1.0f, // Deliberately ignore zoom on the canvas element. &fill_flags_for_filter, &stroke_flags_for_filter);
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp index 31e4afe..1482e9b 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorker.cpp
@@ -41,7 +41,6 @@ #include "modules/EventTargetModules.h" #include "modules/serviceworkers/ServiceWorkerContainerClient.h" #include "platform/bindings/ScriptState.h" -#include "public/platform/WebSecurityOrigin.h" #include "public/platform/WebString.h" #include "third_party/WebKit/public/mojom/service_worker/service_worker_state.mojom-blink.h" @@ -78,9 +77,8 @@ return; } - handle_->ServiceWorker()->PostMessage( - ToTransferableMessage(std::move(msg)), - WebSecurityOrigin(GetExecutionContext()->GetSecurityOrigin())); + handle_->ServiceWorker()->PostMessageToServiceWorker( + ToTransferableMessage(std::move(msg))); } ScriptPromise ServiceWorker::InternalsTerminate(ScriptState* script_state) {
diff --git a/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.cpp b/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.cpp index 76c98e8..03b53ac 100644 --- a/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.cpp +++ b/third_party/WebKit/Source/platform/graphics/DrawLooperBuilder.cpp
@@ -39,8 +39,8 @@ #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/core/SkDrawLooper.h" +#include "third_party/skia/include/core/SkMaskFilter.h" #include "third_party/skia/include/core/SkPaint.h" -#include "third_party/skia/include/effects/SkBlurMaskFilter.h" namespace blink { @@ -93,11 +93,9 @@ if (blur) { const SkScalar sigma = SkBlurRadiusToSigma(blur); - uint32_t mf_flags = SkBlurMaskFilter::kHighQuality_BlurFlag; - if (shadow_transform_mode == kShadowIgnoresTransforms) - mf_flags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag; + const bool respectCTM = shadow_transform_mode != kShadowIgnoresTransforms; paint->setMaskFilter( - SkBlurMaskFilter::Make(kNormal_SkBlurStyle, sigma, mf_flags)); + SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, sigma, respectCTM)); } paint->setColorFilter(
diff --git a/third_party/WebKit/Source/platform/heap/Heap.cpp b/third_party/WebKit/Source/platform/heap/Heap.cpp index b5b0f74c..719289b7 100644 --- a/third_party/WebKit/Source/platform/heap/Heap.cpp +++ b/third_party/WebKit/Source/platform/heap/Heap.cpp
@@ -808,14 +808,14 @@ } void ThreadHeap::WriteBarrier(const void* value) { - if (!value || !ThreadState::Current()->IsIncrementalMarking()) + if (!value || !thread_state_->IsIncrementalMarking()) return; WriteBarrierInternal(PageFromObject(value), value); } void ThreadHeap::WriteBarrierInternal(BasePage* page, const void* value) { - DCHECK(ThreadState::Current()->IsIncrementalMarking()); + DCHECK(thread_state_->IsIncrementalMarking()); DCHECK(page->IsIncrementalMarking()); DCHECK(value); HeapObjectHeader* const header =
diff --git a/third_party/WebKit/Source/platform/heap/HeapAllocator.h b/third_party/WebKit/Source/platform/heap/HeapAllocator.h index 12182fb..e29a6a56 100644 --- a/third_party/WebKit/Source/platform/heap/HeapAllocator.h +++ b/third_party/WebKit/Source/platform/heap/HeapAllocator.h
@@ -130,7 +130,10 @@ static void BackingWriteBarrier(void* address) { #if BUILDFLAG(BLINK_HEAP_INCREMENTAL_MARKING) - ThreadState::Current()->Heap().WriteBarrier(address); + if (!address) + return; + ThreadState* state = PageFromObject(address)->Arena()->GetThreadState(); + state->Heap().WriteBarrier(address); #endif } @@ -171,11 +174,6 @@ return ThreadHeap::IsHeapObjectAlive(object); } - template <typename VisitorDispatcher> - static void MarkNoTracing(VisitorDispatcher visitor, const void* t) { - visitor->MarkNoTracing(t); - } - template <typename VisitorDispatcher, typename T, typename Traits> static void Trace(VisitorDispatcher visitor, T& t) { TraceCollectionIfEnabled<Traits::kWeakHandlingFlag, T, Traits>::Trace(
diff --git a/third_party/WebKit/Source/platform/heap/HeapPage.h b/third_party/WebKit/Source/platform/heap/HeapPage.h index e8bae87..0d3c8dc 100644 --- a/third_party/WebKit/Source/platform/heap/HeapPage.h +++ b/third_party/WebKit/Source/platform/heap/HeapPage.h
@@ -205,6 +205,7 @@ bool IsMarked() const; void Mark(); void Unmark(); + bool TryMark(); // The payload starts directly after the HeapObjectHeader, and the payload // size does not include the sizeof(HeapObjectHeader). @@ -1102,6 +1103,14 @@ encoded_ &= ~kHeaderMarkBitMask; } +NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::TryMark() { + CheckHeader(); + if (encoded_ & kHeaderMarkBitMask) + return false; + encoded_ |= kHeaderMarkBitMask; + return true; +} + NO_SANITIZE_ADDRESS inline bool BasePage::IsValid() const { return GetMagic() == magic_; }
diff --git a/third_party/WebKit/Source/platform/heap/MarkingVisitor.cpp b/third_party/WebKit/Source/platform/heap/MarkingVisitor.cpp index 4ed55c4..3273925 100644 --- a/third_party/WebKit/Source/platform/heap/MarkingVisitor.cpp +++ b/third_party/WebKit/Source/platform/heap/MarkingVisitor.cpp
@@ -27,21 +27,20 @@ MarkingVisitor::~MarkingVisitor() = default; void MarkingVisitor::MarkNoTracingCallback(Visitor* visitor, void* object) { - // TODO(mlippautz): Remove cast; - reinterpret_cast<MarkingVisitor*>(visitor)->MarkNoTracing(object); + reinterpret_cast<MarkingVisitor*>(visitor)->MarkHeaderNoTracing( + HeapObjectHeader::FromPayload(object)); } void MarkingVisitor::RegisterWeakCallback(void* closure, WeakCallback callback) { - DCHECK(GetMarkingMode() != kWeakProcessing); // We don't want to run weak processings when taking a snapshot. - if (GetMarkingMode() == kSnapshotMarking) + if (marking_mode_ == kSnapshotMarking) return; Heap().PushWeakCallback(closure, callback); } void MarkingVisitor::RegisterBackingStoreReference(void* slot) { - if (GetMarkingMode() != kGlobalMarkingWithCompaction) + if (marking_mode_ != kGlobalMarkingWithCompaction) return; Heap().RegisterMovingObjectReference( reinterpret_cast<MovableReference*>(slot)); @@ -50,7 +49,7 @@ void MarkingVisitor::RegisterBackingStoreCallback(void* backing_store, MovingObjectCallback callback, void* callback_data) { - if (GetMarkingMode() != kGlobalMarkingWithCompaction) + if (marking_mode_ != kGlobalMarkingWithCompaction) return; Heap().RegisterMovingObjectCallback( reinterpret_cast<MovableReference>(backing_store), callback, @@ -61,7 +60,6 @@ const void* closure, EphemeronCallback iteration_callback, EphemeronCallback iteration_done_callback) { - DCHECK(GetMarkingMode() != kWeakProcessing); Heap().RegisterWeakTable(const_cast<void*>(closure), iteration_callback, iteration_done_callback); return true;
diff --git a/third_party/WebKit/Source/platform/heap/MarkingVisitor.h b/third_party/WebKit/Source/platform/heap/MarkingVisitor.h index 7d2b146..8bb0f97 100644 --- a/third_party/WebKit/Source/platform/heap/MarkingVisitor.h +++ b/third_party/WebKit/Source/platform/heap/MarkingVisitor.h
@@ -21,9 +21,6 @@ // This visitor just marks objects and ignores weak processing. // This is used for GCType=TakeSnapshot. kSnapshotMarking, - // This visitor is used to trace objects during weak processing. - // This visitor is allowed to trace only already marked objects. - kWeakProcessing, // Perform global marking along with preparing for additional sweep // compaction of heap arenas afterwards. Compared to the GlobalMarking // visitor, this visitor will also register references to objects @@ -38,33 +35,20 @@ MarkingVisitor(ThreadState*, MarkingMode); virtual ~MarkingVisitor(); - inline MarkingMode GetMarkingMode() const { return marking_mode_; } - // Marking implementation. - // This method marks an object and adds it to the set of objects that should - // have their trace method called. Since not all objects have vtables we have - // to have the callback as an explicit argument, but we can use the templated - // one-argument mark method above to automatically provide the callback - // function. - inline void Mark(const void* object_pointer, TraceCallback); - - // Used to mark objects during conservative scanning. + // Marks an object and adds a tracing callback for processing of the object. inline void MarkHeader(HeapObjectHeader*, TraceCallback); - inline void MarkHeaderNoTracing(HeapObjectHeader*); - // Marks the header of an object. Is used for eagerly tracing of objects. - inline bool EnsureMarked(const void* pointer); - - // Used for eagerly marking objects and for delayed marking of backing stores - // when the actual payload is processed differently, e.g., by weak handling. - inline void MarkNoTracing(const void* pointer) { - Mark(pointer, reinterpret_cast<TraceCallback>(0)); - } + // Try to mark an object without tracing. Returns true when the object was not + // marked upon calling. + inline bool MarkHeaderNoTracing(HeapObjectHeader*); // Implementation of the visitor interface. See above for descriptions. void Visit(void* object, TraceDescriptor desc) final { + DCHECK(object); + DCHECK(desc.base_object_payload); // Default mark method of the trait just calls the two-argument mark // method on the visitor. The second argument is the static trace method // of the trait, which by default calls the instance method @@ -87,13 +71,15 @@ // that lead to many recursions. DCHECK(Heap().GetStackFrameDepth().IsAcceptableStackUse()); if (LIKELY(Heap().GetStackFrameDepth().IsSafeToRecurse())) { - if (EnsureMarked(desc.base_object_payload)) { + if (MarkHeaderNoTracing( + HeapObjectHeader::FromPayload(desc.base_object_payload))) { desc.callback(this, desc.base_object_payload); } return; } } - Mark(desc.base_object_payload, desc.callback); + MarkHeader(HeapObjectHeader::FromPayload(desc.base_object_payload), + desc.callback); } void VisitBackingStoreStrongly(void* object, @@ -112,7 +98,6 @@ void VisitBackingStoreWeakly(void* object, void** object_slot, TraceDescriptor desc) final { - DCHECK(GetMarkingMode() != kWeakProcessing); RegisterBackingStoreReference(object_slot); Heap().PushPostMarkingCallback(object, &MarkNoTracingCallback); } @@ -136,54 +121,25 @@ const MarkingMode marking_mode_; }; +inline bool MarkingVisitor::MarkHeaderNoTracing(HeapObjectHeader* header) { + DCHECK(header); + DCHECK(State()->IsInGC() || State()->IsIncrementalMarking()); + // A GC should only mark the objects that belong in its heap. + DCHECK_EQ(State(), + PageFromObject(header->Payload())->Arena()->GetThreadState()); + + return header->TryMark(); +} + inline void MarkingVisitor::MarkHeader(HeapObjectHeader* header, TraceCallback callback) { DCHECK(header); - if (header->IsMarked()) - return; + DCHECK(callback); - DCHECK(ThreadState::Current()->IsInGC() || - ThreadState::Current()->IsIncrementalMarking()); - DCHECK(GetMarkingMode() != kWeakProcessing); - - const void* object_pointer = header->Payload(); - // A GC should only mark the objects that belong in its heap. - DCHECK(&PageFromObject(object_pointer)->Arena()->GetThreadState()->Heap() == - &Heap()); - - header->Mark(); - - if (callback) - Heap().PushTraceCallback(const_cast<void*>(object_pointer), callback); -} - -inline void MarkingVisitor::Mark(const void* object_pointer, - TraceCallback callback) { - if (!object_pointer) - return; - HeapObjectHeader* header = HeapObjectHeader::FromPayload(object_pointer); - MarkHeader(header, callback); -} - -inline void MarkingVisitor::MarkHeaderNoTracing(HeapObjectHeader* header) { - MarkHeader(header, reinterpret_cast<TraceCallback>(0)); -} - -inline bool MarkingVisitor::EnsureMarked(const void* object_pointer) { - if (!object_pointer) - return false; - - HeapObjectHeader* header = HeapObjectHeader::FromPayload(object_pointer); - if (header->IsMarked()) - return false; -#if DCHECK_IS_ON() - MarkNoTracing(object_pointer); -#else - // Inline what the above markNoTracing() call expands to, - // so as to make sure that we do get all the benefits (asserts excepted.) - header->Mark(); -#endif - return true; + if (MarkHeaderNoTracing(header)) { + Heap().PushTraceCallback(reinterpret_cast<void*>(header->Payload()), + callback); + } } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/heap/Visitor.h b/third_party/WebKit/Source/platform/heap/Visitor.h index 79e1d81..f2aa3cd 100644 --- a/third_party/WebKit/Source/platform/heap/Visitor.h +++ b/third_party/WebKit/Source/platform/heap/Visitor.h
@@ -73,8 +73,8 @@ explicit Visitor(ThreadState* state) : state_(state) {} virtual ~Visitor() = default; - inline ThreadState* GetState() const { return state_; } - inline ThreadHeap& Heap() const { return GetState()->Heap(); } + inline ThreadState* State() const { return state_; } + inline ThreadHeap& Heap() const { return state_->Heap(); } // Static visitor implementation forwarding to dynamic interface.
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py index 3d97b82..509e384 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
@@ -1301,8 +1301,22 @@ """Whether a test is considered a web-platform-tests test.""" return re.match(r'(virtual/[^/]+/)?external/wpt/', test) - def should_use_wptserve(self, test): - return self.is_wpt_test(test) + @staticmethod + def should_use_wptserve(test): + return Port.is_wpt_test(test) + + @staticmethod + def should_run_in_wpt_mode(test): + """Whether content_shell should run a test in the WPT mode. + + Some tests outside external/wpt should also be run in the WPT mode in + content_shell, namely: harness-tests/wpt/ (tests for console log + filtering). + """ + # Note: match rules in TestInterfaces::ConfigureForTestWithURL in + # //src/content/shell/test_runner/test_interfaces.cc. + return (Port.is_wpt_test(test) or + re.match(r'harness-tests/wpt/', test)) def start_wptserve(self): """Starts a WPT web server. @@ -1814,12 +1828,19 @@ return [] def should_run_as_pixel_test(self, test_input): + """Whether a test should run as pixel test (when there is no reference). + + This provides the *default* value for whether a test should run as + pixel test. When reference files exist (checked by layout_test_runner + before calling this method), the test always runs as pixel test. + """ if not self._options.pixel_tests: return False if self._options.pixel_test_directories: return any(test_input.test_name.startswith(directory) for directory in self._options.pixel_test_directories) - # TODO(burnik): Make sure this is the right way to do it. - if self.should_use_wptserve(test_input.test_name): + if self.should_run_in_wpt_mode(test_input.test_name): + # WPT should not run as pixel test by default, except reftests + # (for which reference files would exist). return False return True
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py index 56c91da..9c087b63 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base_unittest.py
@@ -38,6 +38,7 @@ from webkitpy.common.system.system_host import SystemHost from webkitpy.common.system.system_host_mock import MockSystemHost from webkitpy.common.path_finder import PathFinder +from webkitpy.layout_tests.models.test_input import TestInput from webkitpy.layout_tests.port.base import Port, VirtualTestSuite from webkitpy.layout_tests.port.test import add_unit_tests_to_mock_filesystem, LAYOUT_TEST_DIR, TestPort @@ -586,18 +587,42 @@ self.assertTrue(port.is_test_file(filesystem, LAYOUT_TEST_DIR + '/external/wpt_automation', 'foo.html')) def test_is_wpt_test(self): - port = self.make_port(with_tests=True) - filesystem = port.host.filesystem - PortTest._add_manifest_to_mock_file_system(filesystem) + self.assertTrue(Port.is_wpt_test('external/wpt/dom/ranges/Range-attributes.html')) + self.assertTrue(Port.is_wpt_test('external/wpt/html/dom/elements/global-attributes/dir_auto-EN-L.html')) + self.assertFalse(Port.is_wpt_test('dom/domparsing/namespaces-1.html')) + self.assertFalse(Port.is_wpt_test('rutabaga')) - self.assertTrue(port.is_wpt_test('external/wpt/dom/ranges/Range-attributes.html')) - self.assertTrue(port.is_wpt_test('external/wpt/html/dom/elements/global-attributes/dir_auto-EN-L.html')) - self.assertFalse(port.is_wpt_test('dom/domparsing/namespaces-1.html')) - self.assertFalse(port.is_wpt_test('rutabaga')) + self.assertTrue(Port.is_wpt_test('virtual/a-name/external/wpt/baz/qux.htm')) + self.assertFalse(Port.is_wpt_test('virtual/external/wpt/baz/qux.htm')) + self.assertFalse(Port.is_wpt_test('not-virtual/a-name/external/wpt/baz/qux.htm')) - self.assertTrue(port.is_wpt_test('virtual/a-name/external/wpt/baz/qux.htm')) - self.assertFalse(port.is_wpt_test('virtual/external/wpt/baz/qux.htm')) - self.assertFalse(port.is_wpt_test('not-virtual/a-name/external/wpt/baz/qux.htm')) + def test_should_use_wptserve(self): + self.assertTrue(Port.should_use_wptserve('external/wpt/dom/interfaces.html')) + self.assertTrue(Port.should_use_wptserve('virtual/a-name/external/wpt/dom/interfaces.html')) + self.assertFalse(Port.should_use_wptserve('harness-tests/wpt/console_logging.html')) + self.assertFalse(Port.should_use_wptserve('dom/domparsing/namespaces-1.html')) + + def test_should_run_as_pixel_test_with_no_pixel_tests_in_args(self): + # With the --no-pixel-tests flag, no tests should run as pixel tests. + options = optparse.Values({'pixel_tests': False}) + port = self.make_port(options=options) + self.assertFalse(port.should_run_as_pixel_test(TestInput('fast/css/001.html'))) + + def test_should_run_as_pixel_test_with_pixel_test_directories(self): + # When --pixel-test-directory is supplied, only tests in those + # directories are allowed to run as pixel tests. + options = optparse.Values({'pixel_tests': True, 'pixel_test_directories': ['foo']}) + port = self.make_port(options=options) + self.assertTrue(port.should_run_as_pixel_test(TestInput('foo/bar.html'))) + self.assertFalse(port.should_run_as_pixel_test(TestInput('bar/baz.html'))) + + def test_should_run_as_pixel_test_default(self): + options = optparse.Values({'pixel_tests': True, 'pixel_test_directories': None}) + port = self.make_port(options=options) + self.assertFalse(port.should_run_as_pixel_test(TestInput('external/wpt/dom/interfaces.html'))) + self.assertFalse(port.should_run_as_pixel_test(TestInput('virtual/a-name/external/wpt/dom/interfaces.html'))) + self.assertFalse(port.should_run_as_pixel_test(TestInput('harness-tests/wpt/console_logging.html'))) + self.assertTrue(port.should_run_as_pixel_test(TestInput('fast/css/001.html'))) def test_is_slow_wpt_test(self): port = self.make_port(with_tests=True)
diff --git a/third_party/WebKit/public/mojom/BUILD.gn b/third_party/WebKit/public/mojom/BUILD.gn index 3ee6b12..14dc0cd 100644 --- a/third_party/WebKit/public/mojom/BUILD.gn +++ b/third_party/WebKit/public/mojom/BUILD.gn
@@ -73,7 +73,6 @@ ":mojom_platform", "//skia/public/interfaces", "//url/mojom:url_mojom_gurl", - "//url/mojom:url_mojom_origin", ] overridden_deps_blink = [ ":mojom_platform" ]
diff --git a/third_party/WebKit/public/mojom/service_worker/service_worker_object.mojom b/third_party/WebKit/public/mojom/service_worker/service_worker_object.mojom index d7a07cd..a83d183c7 100644 --- a/third_party/WebKit/public/mojom/service_worker/service_worker_object.mojom +++ b/third_party/WebKit/public/mojom/service_worker/service_worker_object.mojom
@@ -6,7 +6,6 @@ import "third_party/WebKit/public/mojom/message_port/message_port.mojom"; import "third_party/WebKit/public/mojom/service_worker/service_worker_state.mojom"; -import "url/mojom/origin.mojom"; import "url/mojom/url.mojom"; const int32 kInvalidServiceWorkerHandleId = -1; @@ -38,12 +37,7 @@ // implement ServiceWorker methods. interface ServiceWorkerObjectHost { // Corresponds to ServiceWorker#postMessage(). - // TODO(leonhsl): Remove |source_origin| by having the browser process keep - // track of the origin of this endpoint at binding time. The original legacy - // IPC code this is converted from sent the origin in the IPC message, so it - // was kept as a convenience during migration to Mojo, but we should remove it - // now. - PostMessage(TransferableMessage message, url.mojom.Origin source_origin); + PostMessageToServiceWorker(TransferableMessage message); // Tells the browser process to terminate the service worker. Used in layout // tests to verify behavior when a service worker isn't running. The callback
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorker.h b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorker.h index 072885d6..812807a 100644 --- a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorker.h +++ b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorker.h
@@ -41,7 +41,6 @@ namespace blink { -class WebSecurityOrigin; class WebServiceWorkerProxy; class WebServiceWorker { @@ -70,7 +69,7 @@ return mojom::ServiceWorkerState::kUnknown; } - virtual void PostMessage(TransferableMessage, const WebSecurityOrigin&) = 0; + virtual void PostMessageToServiceWorker(TransferableMessage) = 0; using TerminateForTestingCallback = WebCallbacks<void, void>; virtual void TerminateForTesting(
diff --git a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h index 4416d015..e2d195b 100644 --- a/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h +++ b/third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h
@@ -42,6 +42,7 @@ struct WebBackgroundFetchSettledFetch; struct WebCanMakePaymentEventData; class WebDataConsumerHandle; +class WebSecurityOrigin; class WebServiceWorkerRequest; class WebString; struct WebNotificationData;
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index dc3244d..93e01fa 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: a8ecdbc973d969a87aaa2efffb1668efb52b799d +Revision: c27a1aaea0861852c6d92945b68856586e0cd51d License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes @@ -37,9 +37,3 @@ Local Modifications: - codereview.settings has been excluded. - thread_log_messages.cc (using ThreadLocalStorage::Slot instead of StaticSlot) - - util/linux/memory_map.cc - - util/mach/symbolic_constants_mach.cc - - util/posix/symbolic_constants_posix.cc - - util/stdlib/string_number_conversion.h - - util/stdlib/string_number_conversion.cc - - util/stdlib/string_number_conversion_test.cc
diff --git a/third_party/crashpad/crashpad/.gitignore b/third_party/crashpad/crashpad/.gitignore index e6daaab..d225542 100644 --- a/third_party/crashpad/crashpad/.gitignore +++ b/third_party/crashpad/crashpad/.gitignore
@@ -15,6 +15,9 @@ /third_party/fuchsia/qemu /third_party/fuchsia/sdk /third_party/gtest/gtest +/third_party/linux/.cipd +/third_party/linux/clang +/third_party/linux/sysroot /third_party/gyp/gyp /third_party/mini_chromium/mini_chromium /third_party/zlib/zlib
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS index 6936f9f..d118f600 100644 --- a/third_party/crashpad/crashpad/DEPS +++ b/third_party/crashpad/crashpad/DEPS
@@ -14,6 +14,7 @@ vars = { 'chromium_git': 'https://chromium.googlesource.com', + 'pull_linux_clang': False } deps = { @@ -28,7 +29,7 @@ '5e2b3ddde7cda5eb6bc09a5546a76b00e49d888f', 'crashpad/third_party/mini_chromium/mini_chromium': Var('chromium_git') + '/chromium/mini_chromium@' + - '3b953302848580cdf23b50402befc0ae09d03ff9', + 'ef0df1119b40cfa2773d5960e239d4b960310869', 'crashpad/third_party/zlib/zlib': Var('chromium_git') + '/chromium/src/third_party/zlib@' + '13dc246a58e4b72104d35f9b1809af95221ebda7', @@ -115,8 +116,37 @@ }, { # This uses “cipd install” so that mac-amd64 and linux-amd64 can coexist - # peacefully. “cipd ensure” would remove the Linux package when running on a - # macOS build host and vice-versa. https://crbug.com/789364. + # peacefully. “cipd ensure” would remove the macOS package when running on a + # Linux build host and vice-versa. https://crbug.com/789364. This package is + # only updated when the solution in .gclient includes an entry like: + # "custom_vars": { "pull_linux_clang": True } + 'name': 'clang_linux', + 'pattern': '.', + 'condition': 'checkout_linux and pull_linux_clang', + 'action': [ + 'cipd', + 'install', + # sic, using Fuchsia team's generic build of clang for linux-amd64 to + # build for linux-amd64 target too. + 'fuchsia/clang/linux-amd64', + 'latest', + '-root', 'crashpad/third_party/linux/clang/linux-amd64', + '-log-level', 'info', + ], + }, + { + # If using a local clang ("pull_linux_clang" above), also pull down a + # sysroot. + 'name': 'clang_linux', + 'pattern': '.', + 'condition': 'checkout_linux and pull_linux_clang', + 'action': [ + 'crashpad/build/install_linux_sysroot.py', + ], + }, + { + # Same rationale for using "install" rather than "ensure" as for first clang + # package. https://crbug.com/789364. 'name': 'fuchsia_clang_mac', 'pattern': '.', 'condition': 'checkout_fuchsia and host_os == "mac"', @@ -130,9 +160,8 @@ ], }, { - # This uses “cipd install” so that mac-amd64 and linux-amd64 can coexist - # peacefully. “cipd ensure” would remove the macOS package when running on a - # Linux build host and vice-versa. https://crbug.com/789364. + # Same rationale for using "install" rather than "ensure" as for first clang + # package. https://crbug.com/789364. 'name': 'fuchsia_clang_linux', 'pattern': '.', 'condition': 'checkout_fuchsia and host_os == "linux"',
diff --git a/third_party/crashpad/crashpad/build/BUILDCONFIG.gn b/third_party/crashpad/crashpad/build/BUILDCONFIG.gn index 67d56ae..0e6da16 100644 --- a/third_party/crashpad/crashpad/build/BUILDCONFIG.gn +++ b/third_party/crashpad/crashpad/build/BUILDCONFIG.gn
@@ -35,7 +35,7 @@ if (current_os == "win") { set_default_toolchain( - "//third_party/mini_chromium/mini_chromium/build:msvc_toolchain") + "//third_party/mini_chromium/mini_chromium/build:msvc_toolchain_$current_cpu") } else { set_default_toolchain( "//third_party/mini_chromium/mini_chromium/build:gcc_like_toolchain") @@ -54,8 +54,10 @@ ] _default_executable_configs = - _default_configs + - [ "//third_party/mini_chromium/mini_chromium/build:executable" ] + _default_configs + [ + "//third_party/mini_chromium/mini_chromium/build:executable", + "//third_party/mini_chromium/mini_chromium/build:win_console", + ] set_defaults("source_set") { configs = _default_configs
diff --git a/third_party/crashpad/crashpad/build/install_linux_sysroot.py b/third_party/crashpad/crashpad/build/install_linux_sysroot.py new file mode 100755 index 0000000..afa8815 --- /dev/null +++ b/third_party/crashpad/crashpad/build/install_linux_sysroot.py
@@ -0,0 +1,74 @@ +#!/usr/bin/env python + +# Copyright 2018 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. + +# Various code adapted from: +# https://cs.chromium.org/chromium/src/build/linux/sysroot_scripts/install-sysroot.py + +import os +import shutil +import subprocess +import sys +import urllib2 + + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Sysroot revision from: +# https://cs.chromium.org/chromium/src/build/linux/sysroot_scripts/sysroots.json +SERVER = 'https://commondatastorage.googleapis.com' +PATH = 'chrome-linux-sysroot/toolchain' +REVISION = '3c248ba4290a5ad07085b7af07e6785bf1ae5b66' +FILENAME = 'debian_stretch_amd64_sysroot.tar.xz' + +def main(): + url = '%s/%s/%s/%s' % (SERVER, PATH, REVISION, FILENAME) + + sysroot = os.path.join(SCRIPT_DIR, os.pardir, + 'third_party', 'linux', 'sysroot') + + stamp = os.path.join(sysroot, '.stamp') + if os.path.exists(stamp): + with open(stamp) as s: + if s.read() == url: + return + + print 'Installing Debian root image from %s' % url + + if os.path.isdir(sysroot): + shutil.rmtree(sysroot) + os.mkdir(sysroot) + tarball = os.path.join(sysroot, FILENAME) + print 'Downloading %s' % url + + for _ in range(3): + response = urllib2.urlopen(url) + with open(tarball, 'wb') as f: + f.write(response.read()) + break + else: + raise Exception('Failed to download %s' % url) + + subprocess.check_call(['tar', 'xf', tarball, '-C', sysroot]) + + os.remove(tarball) + + with open(stamp, 'w') as s: + s.write(url) + + +if __name__ == '__main__': + main() + sys.exit(0)
diff --git a/third_party/crashpad/crashpad/build/run_tests.py b/third_party/crashpad/crashpad/build/run_tests.py index 6c2dacf4..efd0aa4 100755 --- a/third_party/crashpad/crashpad/build/run_tests.py +++ b/third_party/crashpad/crashpad/build/run_tests.py
@@ -70,10 +70,11 @@ if gn_path: # Look for a GN “target_os”. - popen = subprocess.Popen( - [gn_path, 'args', binary_dir, '--list=target_os', '--short'], - shell=IS_WINDOWS_HOST, stdout=subprocess.PIPE, stderr=open(os.devnull), - cwd=CRASHPAD_DIR) + popen = subprocess.Popen([gn_path, '--root=' + CRASHPAD_DIR, + 'args', binary_dir, + '--list=target_os', '--short'], + shell=IS_WINDOWS_HOST, + stdout=subprocess.PIPE, stderr=open(os.devnull)) value = popen.communicate()[0] if popen.returncode == 0: match = re.match('target_os = "(.*)"$', value.decode('utf-8')) @@ -310,13 +311,18 @@ def _GenerateFuchsiaRuntimeDepsFiles(binary_dir, tests): """Ensures a <binary_dir>/<test>.runtime_deps file exists for each test.""" - targets_file = os.path.abspath(os.path.join(binary_dir, 'targets.txt')) + targets_file = os.path.join(binary_dir, 'targets.txt') with open(targets_file, 'wb') as f: f.write('//:' + '\n//:'.join(tests) + '\n') gn_path = _FindGNFromBinaryDir(binary_dir) subprocess.check_call( - [gn_path, 'gen', binary_dir, '--runtime-deps-list-file=' + targets_file], - cwd=CRASHPAD_DIR) + [gn_path, '--root=' + CRASHPAD_DIR, 'gen', binary_dir, + '--runtime-deps-list-file=' + targets_file]) + + # Run again so that --runtime-deps-list-file isn't in the regen rule. See + # https://crbug.com/814816. + subprocess.check_call( + [gn_path, '--root=' + CRASHPAD_DIR, 'gen', binary_dir]) def _HandleOutputFromFuchsiaLogListener(process, done_message): @@ -373,7 +379,8 @@ staging_root = test_root + '/pkg' # Make a staging directory tree on the target. - directories_to_create = [tmp_root, '%s/bin' % staging_root, + directories_to_create = [tmp_root, + '%s/bin' % staging_root, '%s/assets' % staging_root] netruncmd(['mkdir', '-p'] + directories_to_create) @@ -396,7 +403,8 @@ target_path = os.path.join( staging_root, 'bin', local_path[len(binary_dir)+1:]) else: - target_path = os.path.join(staging_root, 'assets', local_path) + relative_path = os.path.relpath(local_path, CRASHPAD_DIR) + target_path = os.path.join(staging_root, 'assets', relative_path) netcp_path = os.path.join(sdk_root, 'tools', 'netcp') subprocess.check_call([netcp_path, local_path, device_name + ':' + target_path],
diff --git a/third_party/crashpad/crashpad/client/BUILD.gn b/third_party/crashpad/crashpad/client/BUILD.gn index f054e7ca..cb4161f50 100644 --- a/third_party/crashpad/crashpad/client/BUILD.gn +++ b/third_party/crashpad/crashpad/client/BUILD.gn
@@ -36,8 +36,6 @@ if (crashpad_is_mac) { sources += [ - "capture_context_mac.S", - "capture_context_mac.h", "crash_report_database_mac.mm", "crashpad_client_mac.cc", "simulate_crash_mac.cc", @@ -46,7 +44,14 @@ } if (crashpad_is_linux || crashpad_is_android) { - sources += [ "crashpad_client_linux.cc" ] + sources += [ + "crashpad_client_linux.cc", + "simulate_crash_linux.h", + ] + } + + if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) { + sources += [ "crashpad_info_note.S" ] } if (crashpad_is_win) { @@ -59,11 +64,14 @@ if (crashpad_is_fuchsia) { sources += [ - "crash_report_database_fuchsia.cc", "crashpad_client_fuchsia.cc", ] } + if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) { + sources += [ "crash_report_database_generic.cc" ] + } + public_configs = [ "..:crashpad_config" ] deps = [ @@ -92,16 +100,17 @@ ] if (crashpad_is_mac) { - sources += [ - "capture_context_mac_test.cc", - "simulate_crash_mac_test.cc", - ] + sources += [ "simulate_crash_mac_test.cc" ] } if (crashpad_is_win) { sources += [ "crashpad_client_win_test.cc" ] } + if (crashpad_is_linux || crashpad_is_android) { + sources += [ "crashpad_client_linux_test.cc" ] + } + deps = [ ":client", "../compat",
diff --git a/third_party/crashpad/crashpad/client/capture_context_mac.h b/third_party/crashpad/crashpad/client/capture_context_mac.h deleted file mode 100644 index 74e440e..0000000 --- a/third_party/crashpad/crashpad/client/capture_context_mac.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2014 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_CLIENT_CAPTURE_CONTEXT_MAC_H_ -#define CRASHPAD_CLIENT_CAPTURE_CONTEXT_MAC_H_ - -#include <mach/mach.h> - -#include "build/build_config.h" - -namespace crashpad { - -#if defined(ARCH_CPU_X86_FAMILY) -using NativeCPUContext = x86_thread_state; -#endif - -//! \brief Saves the CPU context. -//! -//! The CPU context will be captured as accurately and completely as possible, -//! containing an atomic snapshot at the point of this function’s return. This -//! function does not modify any registers. -//! -//! \param[out] cpu_context The structure to store the context in. -//! -//! \note On x86_64, the value for `%%rdi` will be populated with the address of -//! this function’s argument, as mandated by the ABI. If the value of -//! `%%rdi` prior to calling this function is needed, it must be obtained -//! separately prior to calling this function. For example: -//! \code -//! uint64_t rdi; -//! asm("movq %%rdi, %0" : "=m"(rdi)); -//! \endcode -void CaptureContext(NativeCPUContext* cpu_context); - -} // namespace crashpad - -#endif // CRASHPAD_CLIENT_CAPTURE_CONTEXT_MAC_H_
diff --git a/third_party/crashpad/crashpad/client/capture_context_mac_test.cc b/third_party/crashpad/crashpad/client/capture_context_mac_test.cc deleted file mode 100644 index 15640210..0000000 --- a/third_party/crashpad/crashpad/client/capture_context_mac_test.cc +++ /dev/null
@@ -1,158 +0,0 @@ -// Copyright 2014 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 "client/capture_context_mac.h" - -#include <mach/mach.h> -#include <stdint.h> - -#include <algorithm> - -#include "build/build_config.h" -#include "gtest/gtest.h" -#include "util/misc/address_sanitizer.h" -#include "util/misc/implicit_cast.h" - -namespace crashpad { -namespace test { -namespace { - -// If the context structure has fields that tell whether it’s valid, such as -// magic numbers or size fields, sanity-checks those fields for validity with -// fatal gtest assertions. For other fields, where it’s possible to reason about -// their validity based solely on their contents, sanity-checks via nonfatal -// gtest assertions. -void SanityCheckContext(const NativeCPUContext& context) { -#if defined(ARCH_CPU_X86) - ASSERT_EQ(implicit_cast<thread_state_flavor_t>(context.tsh.flavor), - implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE32)); - ASSERT_EQ(implicit_cast<uint32_t>(context.tsh.count), - implicit_cast<uint32_t>(x86_THREAD_STATE32_COUNT)); -#elif defined(ARCH_CPU_X86_64) - ASSERT_EQ(implicit_cast<thread_state_flavor_t>(context.tsh.flavor), - implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE64)); - ASSERT_EQ(implicit_cast<uint32_t>(context.tsh.count), - implicit_cast<uint32_t>(x86_THREAD_STATE64_COUNT)); -#endif - -#if defined(ARCH_CPU_X86_FAMILY) - // The segment registers are only capable of storing 16-bit quantities, but - // the context structure provides native integer-width fields for them. Ensure - // that the high bits are all clear. - // - // Many bit positions in the flags register are reserved and will always read - // a known value. Most reserved bits are always 0, but bit 1 is always 1. - // Check that the reserved bits are all set to their expected values. Note - // that the set of reserved bits may be relaxed over time with newer CPUs, and - // that this test may need to be changed to reflect these developments. The - // current set of reserved bits are 1, 3, 5, 15, and 22 and higher. See Intel - // Software Developer’s Manual, Volume 1: Basic Architecture (253665-051), - // 3.4.3 “EFLAGS Register”, and AMD Architecture Programmer’s Manual, Volume - // 2: System Programming (24593-3.24), 3.1.6 “RFLAGS Register”. -#if defined(ARCH_CPU_X86) - EXPECT_EQ(context.uts.ts32.__cs & ~0xffff, 0u); - EXPECT_EQ(context.uts.ts32.__ds & ~0xffff, 0u); - EXPECT_EQ(context.uts.ts32.__es & ~0xffff, 0u); - EXPECT_EQ(context.uts.ts32.__fs & ~0xffff, 0u); - EXPECT_EQ(context.uts.ts32.__gs & ~0xffff, 0u); - EXPECT_EQ(context.uts.ts32.__ss & ~0xffff, 0u); - EXPECT_EQ(context.uts.ts32.__eflags & 0xffc0802a, 2u); -#elif defined(ARCH_CPU_X86_64) - EXPECT_EQ(context.uts.ts64.__cs & ~UINT64_C(0xffff), 0u); - EXPECT_EQ(context.uts.ts64.__fs & ~UINT64_C(0xffff), 0u); - EXPECT_EQ(context.uts.ts64.__gs & ~UINT64_C(0xffff), 0u); - EXPECT_EQ(context.uts.ts64.__rflags & UINT64_C(0xffffffffffc0802a), 2u); -#endif -#endif -} - -// A CPU-independent function to return the program counter. -uintptr_t ProgramCounterFromContext(const NativeCPUContext& context) { -#if defined(ARCH_CPU_X86) - return context.uts.ts32.__eip; -#elif defined(ARCH_CPU_X86_64) - return context.uts.ts64.__rip; -#endif -} - -// A CPU-independent function to return the stack pointer. -uintptr_t StackPointerFromContext(const NativeCPUContext& context) { -#if defined(ARCH_CPU_X86) - return context.uts.ts32.__esp; -#elif defined(ARCH_CPU_X86_64) - return context.uts.ts64.__rsp; -#endif -} - -void TestCaptureContext() { - NativeCPUContext context_1; - CaptureContext(&context_1); - - { - SCOPED_TRACE("context_1"); - ASSERT_NO_FATAL_FAILURE(SanityCheckContext(context_1)); - } - - // The program counter reference value is this function’s address. The - // captured program counter should be slightly greater than or equal to the - // reference program counter. - uintptr_t pc = ProgramCounterFromContext(context_1); - -#if !defined(ADDRESS_SANITIZER) - // AddressSanitizer can cause enough code bloat that the “nearby” check would - // likely fail. - const uintptr_t kReferencePC = - reinterpret_cast<uintptr_t>(TestCaptureContext); - EXPECT_LT(pc - kReferencePC, 64u); -#endif // !defined(ADDRESS_SANITIZER) - - // Declare sp and context_2 here because all local variables need to be - // declared before computing the stack pointer reference value, so that the - // reference value can be the lowest value possible. - uintptr_t sp; - NativeCPUContext context_2; - - // The stack pointer reference value is the lowest address of a local variable - // in this function. The captured program counter will be slightly less than - // or equal to the reference stack pointer. - const uintptr_t kReferenceSP = - std::min(std::min(reinterpret_cast<uintptr_t>(&context_1), - reinterpret_cast<uintptr_t>(&context_2)), - std::min(reinterpret_cast<uintptr_t>(&pc), - reinterpret_cast<uintptr_t>(&sp))); - sp = StackPointerFromContext(context_1); - EXPECT_LT(kReferenceSP - sp, 512u); - - // Capture the context again, expecting that the stack pointer stays the same - // and the program counter increases. Strictly speaking, there’s no guarantee - // that these conditions will hold, although they do for known compilers even - // under typical optimization. - CaptureContext(&context_2); - - { - SCOPED_TRACE("context_2"); - ASSERT_NO_FATAL_FAILURE(SanityCheckContext(context_2)); - } - - EXPECT_EQ(StackPointerFromContext(context_2), sp); - EXPECT_GT(ProgramCounterFromContext(context_2), pc); -} - -TEST(CaptureContextMac, CaptureContext) { - ASSERT_NO_FATAL_FAILURE(TestCaptureContext()); -} - -} // namespace -} // namespace test -} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/client.gyp b/third_party/crashpad/crashpad/client/client.gyp index f75f9c4..e149a2c 100644 --- a/third_party/crashpad/crashpad/client/client.gyp +++ b/third_party/crashpad/crashpad/client/client.gyp
@@ -33,8 +33,6 @@ 'annotation.h', 'annotation_list.cc', 'annotation_list.h', - 'capture_context_mac.S', - 'capture_context_mac.h', 'crash_report_database.cc', 'crash_report_database.h', 'crash_report_database_mac.mm', @@ -52,6 +50,7 @@ 'simple_string_dictionary.h', 'simple_address_range_bag.h', 'simulate_crash.h', + 'simulate_crash_linux.h', 'simulate_crash_mac.cc', 'simulate_crash_mac.h', 'simulate_crash_win.h', @@ -64,9 +63,18 @@ ], }, }], - ['OS!="mac"', { - 'sources!': [ - 'capture_context_mac.S', + ['OS=="linux" or OS=="android"', { + 'sources': [ + 'crashpad_info_note.S', + 'crash_report_database_generic.cc', + ], + }], + ], + 'target_conditions': [ + ['OS=="android"', { + 'sources/': [ + ['include', '^crashpad_client_linux\\.cc$'], + ['include', '^simulate_crash_linux\\.h$'], ], }], ],
diff --git a/third_party/crashpad/crashpad/client/client_test.gyp b/third_party/crashpad/crashpad/client/client_test.gyp index 4ea4ef2..61a4a7e 100644 --- a/third_party/crashpad/crashpad/client/client_test.gyp +++ b/third_party/crashpad/crashpad/client/client_test.gyp
@@ -37,9 +37,9 @@ 'sources': [ 'annotation_test.cc', 'annotation_list_test.cc', - 'capture_context_mac_test.cc', 'crash_report_database_test.cc', 'crashpad_client_win_test.cc', + 'crashpad_client_linux_test.cc', 'prune_crash_reports_test.cc', 'settings_test.cc', 'simple_address_range_bag_test.cc', @@ -53,6 +53,13 @@ ], }], ], + 'target_conditions': [ + ['OS=="android"', { + 'sources/': [ + ['include', '^crashpad_client_linux_test\\.cc$'], + ], + }], + ], }, ], }
diff --git a/third_party/crashpad/crashpad/client/crash_report_database.cc b/third_party/crashpad/crashpad/client/crash_report_database.cc index 8451e469..afd751d 100644 --- a/third_party/crashpad/crashpad/client/crash_report_database.cc +++ b/third_party/crashpad/crashpad/client/crash_report_database.cc
@@ -14,6 +14,8 @@ #include "client/crash_report_database.h" +#include "build/build_config.h" + namespace crashpad { CrashReportDatabase::Report::Report() @@ -26,22 +28,55 @@ upload_attempts(0), upload_explicitly_requested(false) {} -CrashReportDatabase::CallErrorWritingCrashReport::CallErrorWritingCrashReport( - CrashReportDatabase* database, - NewReport* new_report) - : database_(database), - new_report_(new_report) { +CrashReportDatabase::NewReport::NewReport() + : writer_(std::make_unique<FileWriter>()), uuid_(), file_remover_() {} + +CrashReportDatabase::NewReport::~NewReport() = default; + +bool CrashReportDatabase::NewReport::Initialize( + const base::FilePath& directory, + const base::FilePath::StringType& extension) { + if (!uuid_.InitializeWithNew()) { + return false; + } + +#if defined(OS_WIN) + const std::wstring uuid_string = uuid_.ToString16(); +#else + const std::string uuid_string = uuid_.ToString(); +#endif + + const base::FilePath path = directory.Append(uuid_string + extension); + if (!writer_->Open( + path, FileWriteMode::kCreateOrFail, FilePermissions::kOwnerOnly)) { + return false; + } + file_remover_.reset(path); + return true; } -CrashReportDatabase::CallErrorWritingCrashReport:: - ~CallErrorWritingCrashReport() { - if (new_report_) { - database_->ErrorWritingCrashReport(new_report_); +CrashReportDatabase::UploadReport::UploadReport() + : Report(), reader_(std::make_unique<FileReader>()), database_(nullptr) {} + +CrashReportDatabase::UploadReport::~UploadReport() { + if (database_) { + database_->RecordUploadAttempt(this, false, std::string()); } } -void CrashReportDatabase::CallErrorWritingCrashReport::Disarm() { - new_report_ = nullptr; +bool CrashReportDatabase::UploadReport::Initialize(const base::FilePath path, + CrashReportDatabase* db) { + database_ = db; + return reader_->Open(path); +} + +CrashReportDatabase::OperationStatus CrashReportDatabase::RecordUploadComplete( + std::unique_ptr<const UploadReport> report_in, + const std::string& id) { + UploadReport* report = const_cast<UploadReport*>(report_in.get()); + + report->database_ = nullptr; + return RecordUploadAttempt(report, true, id); } } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/crash_report_database.h b/third_party/crashpad/crashpad/client/crash_report_database.h index 6211789..efa7a770 100644 --- a/third_party/crashpad/crashpad/client/crash_report_database.h +++ b/third_party/crashpad/crashpad/client/crash_report_database.h
@@ -24,6 +24,9 @@ #include "base/files/file_path.h" #include "base/macros.h" #include "util/file/file_io.h" +#include "util/file/file_reader.h" +#include "util/file/file_writer.h" +#include "util/file/scoped_remove_file.h" #include "util/misc/metrics.h" #include "util/misc/uuid.h" @@ -47,7 +50,7 @@ //! processed, or it was has been brought back from 'Completed' state by //! user request. //! 3. Completed: The report has been locally processed, either by uploading -//! it to a collection server and calling RecordUploadAttempt(), or by +//! it to a collection server and calling RecordUploadComplete(), or by //! calling SkipReportUpload(). class CrashReportDatabase { public: @@ -98,44 +101,57 @@ //! \brief A crash report that is in the process of being written. //! - //! An instance of this struct should be created via PrepareNewCrashReport() - //! and destroyed with FinishedWritingCrashReport(). - struct NewReport { - //! The file handle to which the report should be written. - FileHandle handle; + //! An instance of this class should be created via PrepareNewCrashReport(). + class NewReport { + public: + NewReport(); + ~NewReport(); + + //! An open FileWriter with which to write the report. + FileWriter* Writer() const { return writer_.get(); } //! A unique identifier by which this report will always be known to the //! database. - UUID uuid; - - //! The path to the crash report being written. - base::FilePath path; - }; - - //! \brief A scoper to cleanly handle the interface requirement imposed by - //! PrepareNewCrashReport(). - //! - //! Calls ErrorWritingCrashReport() upon destruction unless disarmed by - //! calling Disarm(). Armed upon construction. - class CallErrorWritingCrashReport { - public: - //! \brief Arms the object to call ErrorWritingCrashReport() on \a database - //! with an argument of \a new_report on destruction. - CallErrorWritingCrashReport(CrashReportDatabase* database, - NewReport* new_report); - - //! \brief Calls ErrorWritingCrashReport() if the object is armed. - ~CallErrorWritingCrashReport(); - - //! \brief Disarms the object so that CallErrorWritingCrashReport() will not - //! be called upon destruction. - void Disarm(); + const UUID& ReportID() { return uuid_; } private: - CrashReportDatabase* database_; // weak - NewReport* new_report_; // weak + friend class CrashReportDatabaseGeneric; + friend class CrashReportDatabaseMac; + friend class CrashReportDatabaseWin; - DISALLOW_COPY_AND_ASSIGN(CallErrorWritingCrashReport); + bool Initialize(const base::FilePath& directory, + const base::FilePath::StringType& extension); + + std::unique_ptr<FileWriter> writer_; + UUID uuid_; + ScopedRemoveFile file_remover_; + + DISALLOW_COPY_AND_ASSIGN(NewReport); + }; + + //! \brief A crash report that is in the process of being uploaded. + //! + //! An instance of this class should be created via GetReportForUploading(). + class UploadReport : public Report { + public: + UploadReport(); + virtual ~UploadReport(); + + // An open FileReader with which to read the report. + FileReader* Reader() const { return reader_.get(); } + + private: + friend class CrashReportDatabase; + friend class CrashReportDatabaseGeneric; + friend class CrashReportDatabaseMac; + friend class CrashReportDatabaseWin; + + bool Initialize(const base::FilePath path, CrashReportDatabase* database); + + std::unique_ptr<FileReader> reader_; + CrashReportDatabase* database_; + + DISALLOW_COPY_AND_ASSIGN(UploadReport); }; //! \brief The result code for operations performed on a database. @@ -217,49 +233,31 @@ //! \brief Creates a record of a new crash report. //! - //! Callers can then write the crash report using the file handle provided. - //! The caller does not own the new crash report record or its file handle, - //! both of which must be explicitly disposed of by calling - //! FinishedWritingCrashReport() or ErrorWritingCrashReport(). + //! Callers should write the crash report using the FileWriter provided. + //! Callers should then call FinishedWritingCrashReport() to complete report + //! creation. If an error is encountered while writing the crash report, no + //! special action needs to be taken. If FinishedWritingCrashReport() is not + //! called, the report will be removed from the database when \a report is + //! destroyed. //! - //! To arrange to call ErrorWritingCrashReport() during any early return, use - //! CallErrorWritingCrashReport. - //! - //! \param[out] report A NewReport object containing a file handle to which - //! the crash report data should be written. Only valid if this returns - //! #kNoError. The caller must not delete the NewReport object or close - //! the file handle within. + //! \param[out] report A NewReport object containing a FileWriter with which + //! to write the report data. Only valid if this returns #kNoError. //! //! \return The operation status code. - virtual OperationStatus PrepareNewCrashReport(NewReport** report) = 0; + virtual OperationStatus PrepareNewCrashReport( + std::unique_ptr<NewReport>* report) = 0; - //! \brief Informs the database that a crash report has been written. - //! - //! After calling this method, the database is permitted to move and rename - //! the file at NewReport::path. + //! \brief Informs the database that a crash report has been successfully + //! written. //! //! \param[in] report A NewReport obtained with PrepareNewCrashReport(). The - //! NewReport object and file handle within will be invalidated as part of - //! this call. + //! NewReport object will be invalidated as part of this call. //! \param[out] uuid The UUID of this crash report. //! //! \return The operation status code. - virtual OperationStatus FinishedWritingCrashReport(NewReport* report, - UUID* uuid) = 0; - - //! \brief Informs the database that an error occurred while attempting to - //! write a crash report, and that any resources associated with it should - //! be cleaned up. - //! - //! After calling this method, the database is permitted to remove the file at - //! NewReport::path. - //! - //! \param[in] report A NewReport obtained with PrepareNewCrashReport(). The - //! NewReport object and file handle within will be invalidated as part of - //! this call. - //! - //! \return The operation status code. - virtual OperationStatus ErrorWritingCrashReport(NewReport* report) = 0; + virtual OperationStatus FinishedWritingCrashReport( + std::unique_ptr<NewReport> report, + UUID* uuid) = 0; //! \brief Returns the crash report record for the unique identifier. //! @@ -288,42 +286,38 @@ //! \return The operation status code. virtual OperationStatus GetCompletedReports(std::vector<Report>* reports) = 0; - //! \brief Obtains a report object for uploading to a collection server. + //! \brief Obtains and locks a report object for uploading to a collection + //! server. //! - //! The file at Report::file_path should be uploaded by the caller, and then - //! the returned Report object must be disposed of via a call to - //! RecordUploadAttempt(). - //! - //! A subsequent call to this method with the same \a uuid is illegal until - //! RecordUploadAttempt() has been called. + //! Callers should upload the crash report using the FileReader provided. + //! Callers should then call RecordUploadComplete() to record a successful + //! upload. If RecordUploadComplete() is not called, the upload attempt will + //! be recorded as unsuccessful and the report lock released when \a report is + //! destroyed. //! //! \param[in] uuid The unique identifier for the crash report record. //! \param[out] report A crash report record for the report to be uploaded. - //! The caller does not own this object. Only valid if this returns - //! #kNoError. + //! Only valid if this returns #kNoError. //! //! \return The operation status code. - virtual OperationStatus GetReportForUploading(const UUID& uuid, - const Report** report) = 0; + virtual OperationStatus GetReportForUploading( + const UUID& uuid, + std::unique_ptr<const UploadReport>* report) = 0; - //! \brief Adjusts a crash report record’s metadata to account for an upload - //! attempt, and updates the last upload attempt time as returned by + //! \brief Records a successful upload for a report and updates the last + //! upload attempt time as returned by //! Settings::GetLastUploadAttemptTime(). //! - //! After calling this method, the database is permitted to move and rename - //! the file at Report::file_path. - //! - //! \param[in] report The report object obtained from - //! GetReportForUploading(). This object is invalidated after this call. - //! \param[in] successful Whether the upload attempt was successful. - //! \param[in] id The identifier assigned to this crash report by the - //! collection server. Must be empty if \a successful is `false`; may be - //! empty if it is `true`. + //! \param[in] report A UploadReport object obtained from + //! GetReportForUploading(). The UploadReport object will be invalidated + //! and the report unlocked as part of this call. + //! \param[in] id The possibly empty identifier assigned to this crash report + //! by the collection server. //! //! \return The operation status code. - virtual OperationStatus RecordUploadAttempt(const Report* report, - bool successful, - const std::string& id) = 0; + OperationStatus RecordUploadComplete( + std::unique_ptr<const UploadReport> report, + const std::string& id); //! \brief Moves a report from the pending state to the completed state, but //! without the report being uploaded. @@ -355,10 +349,37 @@ //! \return The operation status code. virtual OperationStatus RequestUpload(const UUID& uuid) = 0; + //! \brief Cleans the database of expired lockfiles, metadata without report + //! files, and report files without metadata. + //! + //! This method does nothing on the macOS and Windows implementations of the + //! database. + //! + //! \param[in] lockfile_ttl The number of seconds at which lockfiles or new + //! report files are considered expired. + //! \return The number of reports cleaned. + virtual int CleanDatabase(time_t lockfile_ttl) { return 0; } + protected: CrashReportDatabase() {} private: + //! \brief Adjusts a crash report record’s metadata to account for an upload + //! attempt, and updates the last upload attempt time as returned by + //! Settings::GetLastUploadAttemptTime(). + //! + //! \param[in] report The report object obtained from + //! GetReportForUploading(). + //! \param[in] successful Whether the upload attempt was successful. + //! \param[in] id The identifier assigned to this crash report by the + //! collection server. Must be empty if \a successful is `false`; may be + //! empty if it is `true`. + //! + //! \return The operation status code. + virtual OperationStatus RecordUploadAttempt(UploadReport* report, + bool successful, + const std::string& id) = 0; + DISALLOW_COPY_AND_ASSIGN(CrashReportDatabase); };
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_fuchsia.cc b/third_party/crashpad/crashpad/client/crash_report_database_fuchsia.cc deleted file mode 100644 index 0a7157c8..0000000 --- a/third_party/crashpad/crashpad/client/crash_report_database_fuchsia.cc +++ /dev/null
@@ -1,35 +0,0 @@ -// 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 "client/crash_report_database.h" - -#include "base/logging.h" - -namespace crashpad { - -// static -std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize( - const base::FilePath& path) { - NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 - return std::unique_ptr<CrashReportDatabase>(); -} - -// static -std::unique_ptr<CrashReportDatabase> -CrashReportDatabase::InitializeWithoutCreating(const base::FilePath& path) { - NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 - return std::unique_ptr<CrashReportDatabase>(); -} - -} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_generic.cc b/third_party/crashpad/crashpad/client/crash_report_database_generic.cc new file mode 100644 index 0000000..fc1d04e --- /dev/null +++ b/third_party/crashpad/crashpad/client/crash_report_database_generic.cc
@@ -0,0 +1,843 @@ +// Copyright 2018 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 "client/crash_report_database.h" + +#include <stdint.h> +#include <sys/types.h> + +#include <utility> + +#include "base/logging.h" +#include "build/build_config.h" +#include "client/settings.h" +#include "util/file/directory_reader.h" +#include "util/file/filesystem.h" +#include "util/misc/initialization_state_dcheck.h" + +namespace crashpad { + +namespace { + +// Reads from the current file position to EOF and returns as a string of bytes. +bool ReadRestOfFileAsString(FileHandle handle, std::string* contents) { + char buffer[4096]; + FileOperationResult rv; + std::string local_contents; + while ((rv = ReadFile(handle, buffer, sizeof(buffer))) > 0) { + local_contents.append(buffer, rv); + } + if (rv < 0) { + PLOG(ERROR) << "ReadFile"; + return false; + } + contents->swap(local_contents); + return true; +} + +base::FilePath ReplaceFinalExtension( + const base::FilePath& path, + const base::FilePath::StringType extension) { + return base::FilePath(path.RemoveFinalExtension().value() + extension); +} + +using OperationStatus = CrashReportDatabase::OperationStatus; + +constexpr base::FilePath::CharType kSettings[] = + FILE_PATH_LITERAL("settings.dat"); + +constexpr base::FilePath::CharType kCrashReportExtension[] = + FILE_PATH_LITERAL(".dmp"); +constexpr base::FilePath::CharType kMetadataExtension[] = + FILE_PATH_LITERAL(".meta"); +constexpr base::FilePath::CharType kLockExtension[] = + FILE_PATH_LITERAL(".lock"); + +constexpr base::FilePath::CharType kNewDirectory[] = FILE_PATH_LITERAL("new"); +constexpr base::FilePath::CharType kPendingDirectory[] = + FILE_PATH_LITERAL("pending"); +constexpr base::FilePath::CharType kCompletedDirectory[] = + FILE_PATH_LITERAL("completed"); + +constexpr const base::FilePath::CharType* kReportDirectories[] = { + kNewDirectory, + kPendingDirectory, + kCompletedDirectory, +}; + +enum { + //! \brief Corresponds to uploaded bit of the report state. + kAttributeUploaded = 1 << 0, + + //! \brief Corresponds to upload_explicity_requested bit of the report state. + kAttributeUploadExplicitlyRequested = 1 << 1, +}; + +struct ReportMetadata { + static constexpr int32_t kVersion = 1; + + int32_t version = kVersion; + int32_t upload_attempts = 0; + int64_t last_upload_attempt_time = 0; + time_t creation_time = 0; + uint8_t attributes = 0; +}; + +// A lock held while using database resources. +class ScopedLockFile { + public: + ScopedLockFile() = default; + ~ScopedLockFile() = default; + + ScopedLockFile& operator=(ScopedLockFile&& other) { + lock_file_.reset(other.lock_file_.release()); + return *this; + } + + // Attempt to acquire a lock for the report at report_path. + // Return `true` on success, otherwise `false`. + bool ResetAcquire(const base::FilePath& report_path) { + lock_file_.reset(); + + base::FilePath lock_path(report_path.RemoveFinalExtension().value() + + kLockExtension); + ScopedFileHandle lock_fd(LoggingOpenFileForWrite( + lock_path, FileWriteMode::kCreateOrFail, FilePermissions::kOwnerOnly)); + if (!lock_fd.is_valid()) { + return false; + } + lock_file_.reset(lock_path); + + time_t timestamp = time(nullptr); + if (!LoggingWriteFile(lock_fd.get(), ×tamp, sizeof(timestamp))) { + return false; + } + + return true; + } + + // Returns `true` if the lock is held. + bool is_valid() const { return lock_file_.is_valid(); } + + // Returns `true` if the lockfile at lock_path has expired. + static bool IsExpired(const base::FilePath& lock_path, time_t lockfile_ttl) { + time_t now = time(nullptr); + + timespec filetime; + if (FileModificationTime(lock_path, &filetime) && + filetime.tv_sec > now + lockfile_ttl) { + return false; + } + + ScopedFileHandle lock_fd(LoggingOpenFileForReadAndWrite( + lock_path, FileWriteMode::kReuseOrFail, FilePermissions::kOwnerOnly)); + if (!lock_fd.is_valid()) { + return false; + } + + time_t timestamp; + if (!LoggingReadFileExactly(lock_fd.get(), ×tamp, sizeof(timestamp))) { + return false; + } + + return now >= timestamp + lockfile_ttl; + } + + private: + ScopedRemoveFile lock_file_; + + DISALLOW_COPY_AND_ASSIGN(ScopedLockFile); +}; + +} // namespace + +class CrashReportDatabaseGeneric : public CrashReportDatabase { + public: + CrashReportDatabaseGeneric(); + ~CrashReportDatabaseGeneric() override; + + bool Initialize(const base::FilePath& path, bool may_create); + + // CrashReportDatabase: + Settings* GetSettings() override; + OperationStatus PrepareNewCrashReport( + std::unique_ptr<NewReport>* report) override; + OperationStatus FinishedWritingCrashReport(std::unique_ptr<NewReport> report, + UUID* uuid) override; + OperationStatus LookUpCrashReport(const UUID& uuid, Report* report) override; + OperationStatus GetPendingReports(std::vector<Report>* reports) override; + OperationStatus GetCompletedReports(std::vector<Report>* reports) override; + OperationStatus GetReportForUploading( + const UUID& uuid, + std::unique_ptr<const UploadReport>* report) override; + OperationStatus SkipReportUpload(const UUID& uuid, + Metrics::CrashSkippedReason reason) override; + OperationStatus DeleteReport(const UUID& uuid) override; + OperationStatus RequestUpload(const UUID& uuid) override; + int CleanDatabase(time_t lockfile_ttl) override; + + private: + struct LockfileUploadReport : public UploadReport { + ScopedLockFile lock_file; + }; + + enum ReportState : int32_t { + kUninitialized = -1, + + // Being created by a caller of PrepareNewCrashReport(). + kNew, + + // Created by FinishedWritingCrashReport(), but not yet uploaded. + kPending, + + // Upload completed or skipped. + kCompleted, + + // Specifies either kPending or kCompleted. + kSearchable, + }; + + // CrashReportDatabase: + OperationStatus RecordUploadAttempt(UploadReport* report, + bool successful, + const std::string& id) override; + + // Builds a filepath for the report with the specified uuid and state. + base::FilePath ReportPath(const UUID& uuid, ReportState state); + + // Locates the report with id uuid and returns its file path in path and a + // lock for the report in lock_file. This method succeeds as long as the + // report file exists and the lock can be acquired. No validation is done on + // the existence or content of the metadata file. + OperationStatus LocateAndLockReport(const UUID& uuid, + ReportState state, + base::FilePath* path, + ScopedLockFile* lock_file); + + // Locates, locks, and reads the metadata for the report with the specified + // uuid and state. This method will fail and may remove reports if invalid + // metadata is detected. state may be kPending, kCompleted, or kSearchable. + OperationStatus CheckoutReport(const UUID& uuid, + ReportState state, + base::FilePath* path, + ScopedLockFile* lock_file, + Report* report); + + // Reads metadata for all reports in state and returns it in reports. + OperationStatus ReportsInState(ReportState state, + std::vector<Report>* reports); + + // Cleans lone metadata, reports, or expired locks in a particular state. + int CleanReportsInState(ReportState state, time_t lockfile_ttl); + + // Reads the metadata for a report from path and returns it in report. + static bool ReadMetadata(const base::FilePath& path, Report* report); + + // Wraps ReadMetadata and removes the report from the database on failure. + static bool CleaningReadMetadata(const base::FilePath& path, Report* report); + + // Writes metadata for a new report to the filesystem at path. + static bool WriteNewMetadata(const base::FilePath& path); + + // Writes the metadata for report to the filesystem at path. + static bool WriteMetadata(const base::FilePath& path, const Report& report); + + base::FilePath base_dir_; + Settings settings_; + InitializationStateDcheck initialized_; + + DISALLOW_COPY_AND_ASSIGN(CrashReportDatabaseGeneric); +}; + +CrashReportDatabaseGeneric::CrashReportDatabaseGeneric() = default; + +CrashReportDatabaseGeneric::~CrashReportDatabaseGeneric() = default; + +bool CrashReportDatabaseGeneric::Initialize(const base::FilePath& path, + bool may_create) { + INITIALIZATION_STATE_SET_INITIALIZING(initialized_); + base_dir_ = path; + + if (!IsDirectory(base_dir_, true) && + !(may_create && + LoggingCreateDirectory(base_dir_, FilePermissions::kOwnerOnly, true))) { + return false; + } + + for (const base::FilePath::CharType* subdir : kReportDirectories) { + if (!LoggingCreateDirectory(base_dir_.Append(subdir), + FilePermissions::kOwnerOnly, + true)) { + return false; + } + } + + if (!settings_.Initialize(base_dir_.Append(kSettings))) { + return false; + } + + INITIALIZATION_STATE_SET_VALID(initialized_); + return true; +} + +// static +std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize( + const base::FilePath& path) { + auto database = std::make_unique<CrashReportDatabaseGeneric>(); + return database->Initialize(path, true) ? std::move(database) : nullptr; +} + +// static +std::unique_ptr<CrashReportDatabase> +CrashReportDatabase::InitializeWithoutCreating(const base::FilePath& path) { + auto database = std::make_unique<CrashReportDatabaseGeneric>(); + return database->Initialize(path, false) ? std::move(database) : nullptr; +} + +Settings* CrashReportDatabaseGeneric::GetSettings() { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return &settings_; +} + +OperationStatus CrashReportDatabaseGeneric::PrepareNewCrashReport( + std::unique_ptr<NewReport>* report) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + auto new_report = std::make_unique<NewReport>(); + if (!new_report->Initialize(base_dir_.Append(kNewDirectory), + kCrashReportExtension)) { + return kFileSystemError; + } + + report->reset(new_report.release()); + return kNoError; +} + +OperationStatus CrashReportDatabaseGeneric::FinishedWritingCrashReport( + std::unique_ptr<NewReport> report, + UUID* uuid) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + base::FilePath path = ReportPath(report->ReportID(), kPending); + ScopedLockFile lock_file; + if (!lock_file.ResetAcquire(path)) { + return kBusyError; + } + + if (!WriteNewMetadata(ReplaceFinalExtension(path, kMetadataExtension))) { + return kDatabaseError; + } + + FileOffset size = report->Writer()->Seek(0, SEEK_END); + + report->Writer()->Close(); + if (!MoveFileOrDirectory(report->file_remover_.get(), path)) { + return kFileSystemError; + } + // We've moved the report to pending, so it no longer needs to be removed. + ignore_result(report->file_remover_.release()); + + *uuid = report->ReportID(); + + Metrics::CrashReportPending(Metrics::PendingReportReason::kNewlyCreated); + Metrics::CrashReportSize(size); + + return kNoError; +} + +OperationStatus CrashReportDatabaseGeneric::LookUpCrashReport(const UUID& uuid, + Report* report) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + ScopedLockFile lock_file; + base::FilePath path; + return CheckoutReport(uuid, kSearchable, &path, &lock_file, report); +} + +OperationStatus CrashReportDatabaseGeneric::GetPendingReports( + std::vector<Report>* reports) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return ReportsInState(kPending, reports); +} + +OperationStatus CrashReportDatabaseGeneric::GetCompletedReports( + std::vector<Report>* reports) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return ReportsInState(kCompleted, reports); +} + +OperationStatus CrashReportDatabaseGeneric::GetReportForUploading( + const UUID& uuid, + std::unique_ptr<const UploadReport>* report) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + auto upload_report = std::make_unique<LockfileUploadReport>(); + + base::FilePath path; + OperationStatus os = CheckoutReport( + uuid, kPending, &path, &upload_report->lock_file, upload_report.get()); + if (os != kNoError) { + return os; + } + + if (!upload_report->Initialize(path, this)) { + return kFileSystemError; + } + + report->reset(upload_report.release()); + return kNoError; +} + +OperationStatus CrashReportDatabaseGeneric::SkipReportUpload( + const UUID& uuid, + Metrics::CrashSkippedReason reason) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + Metrics::CrashUploadSkipped(reason); + + base::FilePath path; + ScopedLockFile lock_file; + Report report; + OperationStatus os = + CheckoutReport(uuid, kPending, &path, &lock_file, &report); + if (os != kNoError) { + return os; + } + + base::FilePath completed_path(ReportPath(uuid, kCompleted)); + ScopedLockFile completed_lock_file; + if (!completed_lock_file.ResetAcquire(completed_path)) { + return kBusyError; + } + + report.upload_explicitly_requested = false; + if (!WriteMetadata(completed_path, report)) { + return kDatabaseError; + } + + if (!MoveFileOrDirectory(path, completed_path)) { + return kFileSystemError; + } + + if (!LoggingRemoveFile(ReplaceFinalExtension(path, kMetadataExtension))) { + return kDatabaseError; + } + + return kNoError; +} + +OperationStatus CrashReportDatabaseGeneric::DeleteReport(const UUID& uuid) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + base::FilePath path; + ScopedLockFile lock_file; + OperationStatus os = + LocateAndLockReport(uuid, kSearchable, &path, &lock_file); + if (os != kNoError) { + return os; + } + + if (!LoggingRemoveFile(path)) { + return kFileSystemError; + } + + if (!LoggingRemoveFile(ReplaceFinalExtension(path, kMetadataExtension))) { + return kDatabaseError; + } + + return kNoError; +} + +OperationStatus CrashReportDatabaseGeneric::RequestUpload(const UUID& uuid) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + base::FilePath path; + ScopedLockFile lock_file; + Report report; + OperationStatus os = + CheckoutReport(uuid, kSearchable, &path, &lock_file, &report); + if (os != kNoError) { + return os; + } + + if (report.uploaded) { + return kCannotRequestUpload; + } + + report.upload_explicitly_requested = true; + base::FilePath pending_path = ReportPath(uuid, kPending); + if (!MoveFileOrDirectory(path, pending_path)) { + return kFileSystemError; + } + + if (!WriteMetadata(pending_path, report)) { + return kDatabaseError; + } + + if (pending_path != path) { + if (!LoggingRemoveFile(ReplaceFinalExtension(path, kMetadataExtension))) { + return kDatabaseError; + } + } + + Metrics::CrashReportPending(Metrics::PendingReportReason::kUserInitiated); + return kNoError; +} + +int CrashReportDatabaseGeneric::CleanDatabase(time_t lockfile_ttl) { + int removed = 0; + time_t now = time(nullptr); + + DirectoryReader reader; + const base::FilePath new_dir(base_dir_.Append(kNewDirectory)); + if (reader.Open(new_dir)) { + base::FilePath filename; + DirectoryReader::Result result; + while ((result = reader.NextFile(&filename)) == + DirectoryReader::Result::kSuccess) { + const base::FilePath filepath(new_dir.Append(filename)); + timespec filetime; + if (!FileModificationTime(filepath, &filetime)) { + continue; + } + if (filetime.tv_sec <= now - lockfile_ttl) { + if (LoggingRemoveFile(filepath)) { + ++removed; + } + } + } + } + + removed += CleanReportsInState(kPending, lockfile_ttl); + removed += CleanReportsInState(kCompleted, lockfile_ttl); + return removed; +} + +OperationStatus CrashReportDatabaseGeneric::RecordUploadAttempt( + UploadReport* report, + bool successful, + const std::string& id) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + Metrics::CrashUploadAttempted(successful); + time_t now = time(nullptr); + + report->id = id; + report->uploaded = successful; + report->last_upload_attempt_time = now; + ++report->upload_attempts; + + base::FilePath report_path(report->file_path); + + ScopedLockFile lock_file; + if (successful) { + report->upload_explicitly_requested = false; + + base::FilePath completed_report_path = ReportPath(report->uuid, kCompleted); + + if (!lock_file.ResetAcquire(completed_report_path)) { + return kBusyError; + } + + report->Reader()->Close(); + if (!MoveFileOrDirectory(report_path, completed_report_path)) { + return kFileSystemError; + } + + LoggingRemoveFile(ReplaceFinalExtension(report_path, kMetadataExtension)); + report_path = completed_report_path; + } + + if (!WriteMetadata(report_path, *report)) { + return kDatabaseError; + } + + if (!settings_.SetLastUploadAttemptTime(now)) { + return kDatabaseError; + } + + return kNoError; +} + +base::FilePath CrashReportDatabaseGeneric::ReportPath(const UUID& uuid, + ReportState state) { + DCHECK_NE(state, kUninitialized); + DCHECK_NE(state, kSearchable); + +#if defined(OS_WIN) + const std::wstring uuid_string = uuid.ToString16(); +#else + const std::string uuid_string = uuid.ToString(); +#endif + + return base_dir_.Append(kReportDirectories[state]) + .Append(uuid_string + kCrashReportExtension); +} + +OperationStatus CrashReportDatabaseGeneric::LocateAndLockReport( + const UUID& uuid, + ReportState desired_state, + base::FilePath* path, + ScopedLockFile* lock_file) { + std::vector<ReportState> searchable_states; + if (desired_state == kSearchable) { + searchable_states.push_back(kPending); + searchable_states.push_back(kCompleted); + } else { + DCHECK(desired_state == kPending || desired_state == kCompleted); + searchable_states.push_back(desired_state); + } + + for (const ReportState state : searchable_states) { + base::FilePath local_path(ReportPath(uuid, state)); + ScopedLockFile local_lock; + if (!local_lock.ResetAcquire(local_path)) { + return kBusyError; + } + + if (!IsRegularFile(local_path)) { + continue; + } + + *path = local_path; + *lock_file = std::move(local_lock); + return kNoError; + } + + return kReportNotFound; +} + +OperationStatus CrashReportDatabaseGeneric::CheckoutReport( + const UUID& uuid, + ReportState state, + base::FilePath* path, + ScopedLockFile* lock_file, + Report* report) { + ScopedLockFile local_lock; + base::FilePath local_path; + OperationStatus os = + LocateAndLockReport(uuid, state, &local_path, &local_lock); + if (os != kNoError) { + return os; + } + + if (!CleaningReadMetadata(local_path, report)) { + return kDatabaseError; + } + + *path = local_path; + *lock_file = std::move(local_lock); + return kNoError; +} + +OperationStatus CrashReportDatabaseGeneric::ReportsInState( + ReportState state, + std::vector<Report>* reports) { + DCHECK(reports->empty()); + DCHECK_NE(state, kUninitialized); + DCHECK_NE(state, kSearchable); + DCHECK_NE(state, kNew); + + const base::FilePath dir_path(base_dir_.Append(kReportDirectories[state])); + DirectoryReader reader; + if (!reader.Open(dir_path)) { + return kDatabaseError; + } + + base::FilePath filename; + DirectoryReader::Result result; + while ((result = reader.NextFile(&filename)) == + DirectoryReader::Result::kSuccess) { + const base::FilePath::StringType extension(filename.FinalExtension()); + if (extension.compare(kCrashReportExtension) != 0) { + continue; + } + + const base::FilePath filepath(dir_path.Append(filename)); + ScopedLockFile lock_file; + if (!lock_file.ResetAcquire(filepath)) { + continue; + } + + Report report; + if (!CleaningReadMetadata(filepath, &report)) { + continue; + } + reports->push_back(report); + reports->back().file_path = filepath; + } + return kNoError; +} + +int CrashReportDatabaseGeneric::CleanReportsInState(ReportState state, + time_t lockfile_ttl) { + const base::FilePath dir_path(base_dir_.Append(kReportDirectories[state])); + DirectoryReader reader; + if (!reader.Open(dir_path)) { + return 0; + } + + int removed = 0; + base::FilePath filename; + DirectoryReader::Result result; + while ((result = reader.NextFile(&filename)) == + DirectoryReader::Result::kSuccess) { + const base::FilePath::StringType extension(filename.FinalExtension()); + const base::FilePath filepath(dir_path.Append(filename)); + + // Remove any report files without metadata. + if (extension.compare(kCrashReportExtension) == 0) { + const base::FilePath metadata_path( + ReplaceFinalExtension(filepath, kMetadataExtension)); + ScopedLockFile report_lock; + if (report_lock.ResetAcquire(filepath) && !IsRegularFile(metadata_path) && + LoggingRemoveFile(filepath)) { + ++removed; + } + continue; + } + + // Remove any metadata files without report files. + if (extension.compare(kMetadataExtension) == 0) { + const base::FilePath report_path( + ReplaceFinalExtension(filepath, kCrashReportExtension)); + ScopedLockFile report_lock; + if (report_lock.ResetAcquire(report_path) && + !IsRegularFile(report_path) && LoggingRemoveFile(filepath)) { + ++removed; + } + continue; + } + + // Remove any expired locks only if we can remove the report and metadata. + if (extension.compare(kLockExtension) == 0 && + ScopedLockFile::IsExpired(filepath, lockfile_ttl)) { + const base::FilePath no_ext(filepath.RemoveFinalExtension()); + const base::FilePath report_path(no_ext.value() + kCrashReportExtension); + const base::FilePath metadata_path(no_ext.value() + kMetadataExtension); + if ((IsRegularFile(report_path) && !LoggingRemoveFile(report_path)) || + (IsRegularFile(metadata_path) && !LoggingRemoveFile(metadata_path))) { + continue; + } + + if (LoggingRemoveFile(filepath)) { + ++removed; + } + continue; + } + } + + return removed; +} + +// static +bool CrashReportDatabaseGeneric::ReadMetadata(const base::FilePath& path, + Report* report) { + const base::FilePath metadata_path( + ReplaceFinalExtension(path, kMetadataExtension)); + + ScopedFileHandle handle(LoggingOpenFileForRead(metadata_path)); + if (!handle.is_valid()) { + return false; + } + + if (!report->uuid.InitializeFromString( + path.BaseName().RemoveFinalExtension().value())) { + LOG(ERROR) << "Couldn't interpret report uuid"; + return false; + } + + ReportMetadata metadata; + if (!LoggingReadFileExactly(handle.get(), &metadata, sizeof(metadata))) { + return false; + } + + if (metadata.version != ReportMetadata::kVersion) { + LOG(ERROR) << "metadata version mismatch"; + return false; + } + + if (!ReadRestOfFileAsString(handle.get(), &report->id)) { + return false; + } + + report->upload_attempts = metadata.upload_attempts; + report->last_upload_attempt_time = metadata.last_upload_attempt_time; + report->creation_time = metadata.creation_time; + report->uploaded = (metadata.attributes & kAttributeUploaded) != 0; + report->upload_explicitly_requested = + (metadata.attributes & kAttributeUploadExplicitlyRequested) != 0; + report->file_path = path; + return true; +} + +// static +bool CrashReportDatabaseGeneric::CleaningReadMetadata( + const base::FilePath& path, + Report* report) { + if (ReadMetadata(path, report)) { + return true; + } + + LoggingRemoveFile(path); + LoggingRemoveFile(ReplaceFinalExtension(path, kMetadataExtension)); + return false; +} + +// static +bool CrashReportDatabaseGeneric::WriteNewMetadata(const base::FilePath& path) { + const base::FilePath metadata_path( + ReplaceFinalExtension(path, kMetadataExtension)); + + ScopedFileHandle handle(LoggingOpenFileForWrite(metadata_path, + FileWriteMode::kCreateOrFail, + FilePermissions::kOwnerOnly)); + if (!handle.is_valid()) { + return false; + } + + ReportMetadata metadata; + metadata.creation_time = time(nullptr); + + return LoggingWriteFile(handle.get(), &metadata, sizeof(metadata)); +} + +// static +bool CrashReportDatabaseGeneric::WriteMetadata(const base::FilePath& path, + const Report& report) { + const base::FilePath metadata_path( + ReplaceFinalExtension(path, kMetadataExtension)); + + ScopedFileHandle handle( + LoggingOpenFileForWrite(metadata_path, + FileWriteMode::kTruncateOrCreate, + FilePermissions::kOwnerOnly)); + if (!handle.is_valid()) { + return false; + } + + ReportMetadata metadata; + metadata.creation_time = report.creation_time; + metadata.last_upload_attempt_time = report.last_upload_attempt_time; + metadata.upload_attempts = report.upload_attempts; + metadata.attributes = + (report.uploaded ? kAttributeUploaded : 0) | + (report.upload_explicitly_requested ? kAttributeUploadExplicitlyRequested + : 0); + + return LoggingWriteFile(handle.get(), &metadata, sizeof(metadata)) && + LoggingWriteFile(handle.get(), report.id.c_str(), report.id.size()); +} + +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_mac.mm b/third_party/crashpad/crashpad/client/crash_report_database_mac.mm index 7a9154b..d0197fc 100644 --- a/third_party/crashpad/crashpad/client/crash_report_database_mac.mm +++ b/third_party/crashpad/crashpad/client/crash_report_database_mac.mm
@@ -107,6 +107,8 @@ name.data()); } +} // namespace + //! \brief A CrashReportDatabase that uses HFS+ extended attributes to store //! report metadata. //! @@ -130,24 +132,27 @@ // CrashReportDatabase: Settings* GetSettings() override; - OperationStatus PrepareNewCrashReport(NewReport** report) override; - OperationStatus FinishedWritingCrashReport(NewReport* report, + OperationStatus PrepareNewCrashReport( + std::unique_ptr<NewReport>* report) override; + OperationStatus FinishedWritingCrashReport(std::unique_ptr<NewReport> report, UUID* uuid) override; - OperationStatus ErrorWritingCrashReport(NewReport* report) override; OperationStatus LookUpCrashReport(const UUID& uuid, Report* report) override; OperationStatus GetPendingReports(std::vector<Report>* reports) override; OperationStatus GetCompletedReports(std::vector<Report>* reports) override; - OperationStatus GetReportForUploading(const UUID& uuid, - const Report** report) override; - OperationStatus RecordUploadAttempt(const Report* report, - bool successful, - const std::string& id) override; + OperationStatus GetReportForUploading( + const UUID& uuid, + std::unique_ptr<const UploadReport>* report) override; OperationStatus SkipReportUpload(const UUID& uuid, Metrics::CrashSkippedReason reason) override; OperationStatus DeleteReport(const UUID& uuid) override; OperationStatus RequestUpload(const UUID& uuid) override; private: + // CrashReportDatabase: + OperationStatus RecordUploadAttempt(UploadReport* report, + bool successful, + const std::string& id) override; + //! \brief Report states for use with LocateCrashReport(). //! //! ReportState may be considered to be a bitfield. @@ -161,10 +166,10 @@ //! \brief A private extension of the Report class that maintains bookkeeping //! information of the database. - struct UploadReport : public Report { + struct UploadReportMac : public UploadReport { //! \brief Stores the flock of the file for the duration of //! GetReportForUploading() and RecordUploadAttempt(). - int lock_fd; + base::ScopedFD lock_fd; }; //! \brief Locates a crash report in the database by UUID. @@ -243,7 +248,7 @@ CrashReportDatabaseMac::CrashReportDatabaseMac(const base::FilePath& path) : CrashReportDatabase(), base_dir_(path), - settings_(base_dir_.Append(kSettings)), + settings_(), xattr_new_names_(false), initialized_() { } @@ -268,7 +273,7 @@ return false; } - if (!settings_.Initialize()) + if (!settings_.Initialize(base_dir_.Append(kSettings))) return false; // Do an xattr operation as the last step, to ensure the filesystem has @@ -301,103 +306,67 @@ } CrashReportDatabase::OperationStatus -CrashReportDatabaseMac::PrepareNewCrashReport(NewReport** out_report) { +CrashReportDatabaseMac::PrepareNewCrashReport( + std::unique_ptr<NewReport>* out_report) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::unique_ptr<NewReport> report(new NewReport()); - - uuid_t uuid_gen; - uuid_generate(uuid_gen); - report->uuid.InitializeFromBytes(uuid_gen); - - report->path = - base_dir_.Append(kWriteDirectory) - .Append(report->uuid.ToString() + "." + kCrashReportFileExtension); - - report->handle = HANDLE_EINTR( - open(report->path.value().c_str(), - O_WRONLY | O_EXLOCK | O_CREAT | O_EXCL | O_NOCTTY | O_CLOEXEC, - 0600)); - if (report->handle < 0) { - PLOG(ERROR) << "open " << report->path.value(); + if (!report->Initialize(base_dir_.Append(kWriteDirectory), + std::string(".") + kCrashReportFileExtension)) { return kFileSystemError; } // TODO(rsesek): Potentially use an fsetxattr() here instead. - if (!WriteXattr( - report->path, XattrName(kXattrUUID), report->uuid.ToString())) { - PLOG_IF(ERROR, IGNORE_EINTR(close(report->handle)) != 0) << "close"; + if (!WriteXattr(report->file_remover_.get(), + XattrName(kXattrUUID), + report->ReportID().ToString())) { return kDatabaseError; } - *out_report = report.release(); - + out_report->reset(report.release()); return kNoError; } CrashReportDatabase::OperationStatus -CrashReportDatabaseMac::FinishedWritingCrashReport(NewReport* report, - UUID* uuid) { +CrashReportDatabaseMac::FinishedWritingCrashReport( + std::unique_ptr<NewReport> report, + UUID* uuid) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); - // Takes ownership of the |handle| and the O_EXLOCK. - base::ScopedFD lock(report->handle); - - // Take ownership of the report. - std::unique_ptr<NewReport> scoped_report(report); + const base::FilePath& path = report->file_remover_.get(); // Get the report's UUID to return. std::string uuid_string; - if (ReadXattr(report->path, XattrName(kXattrUUID), - &uuid_string) != XattrStatus::kOK || + if (ReadXattr(path, XattrName(kXattrUUID), &uuid_string) != + XattrStatus::kOK || !uuid->InitializeFromString(uuid_string)) { - LOG(ERROR) << "Failed to read UUID for crash report " - << report->path.value(); + LOG(ERROR) << "Failed to read UUID for crash report " << path.value(); return kDatabaseError; } - if (*uuid != report->uuid) { - LOG(ERROR) << "UUID mismatch for crash report " << report->path.value(); + if (*uuid != report->ReportID()) { + LOG(ERROR) << "UUID mismatch for crash report " << path.value(); return kDatabaseError; } // Record the creation time of this report. - if (!WriteXattrTimeT(report->path, XattrName(kXattrCreationTime), - time(nullptr))) { + if (!WriteXattrTimeT(path, XattrName(kXattrCreationTime), time(nullptr))) { return kDatabaseError; } + FileOffset size = report->Writer()->Seek(0, SEEK_END); + // Move the report to its new location for uploading. base::FilePath new_path = - base_dir_.Append(kUploadPendingDirectory).Append(report->path.BaseName()); - if (rename(report->path.value().c_str(), new_path.value().c_str()) != 0) { - PLOG(ERROR) << "rename " << report->path.value() << " to " - << new_path.value(); + base_dir_.Append(kUploadPendingDirectory).Append(path.BaseName()); + if (rename(path.value().c_str(), new_path.value().c_str()) != 0) { + PLOG(ERROR) << "rename " << path.value() << " to " << new_path.value(); return kFileSystemError; } + ignore_result(report->file_remover_.release()); Metrics::CrashReportPending(Metrics::PendingReportReason::kNewlyCreated); - Metrics::CrashReportSize(report->handle); - - return kNoError; -} - -CrashReportDatabase::OperationStatus -CrashReportDatabaseMac::ErrorWritingCrashReport(NewReport* report) { - INITIALIZATION_STATE_DCHECK_VALID(initialized_); - - // Takes ownership of the |handle| and the O_EXLOCK. - base::ScopedFD lock(report->handle); - - // Take ownership of the report. - std::unique_ptr<NewReport> scoped_report(report); - - // Remove the file that the report would have been written to had no error - // occurred. - if (unlink(report->path.value().c_str()) != 0) { - PLOG(ERROR) << "unlink " << report->path.value(); - return kFileSystemError; - } + Metrics::CrashReportSize(size); return kNoError; } @@ -440,31 +409,36 @@ } CrashReportDatabase::OperationStatus -CrashReportDatabaseMac::GetReportForUploading(const UUID& uuid, - const Report** report) { +CrashReportDatabaseMac::GetReportForUploading( + const UUID& uuid, + std::unique_ptr<const UploadReport>* report) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); - base::FilePath report_path = LocateCrashReport(uuid, kReportStatePending); - if (report_path.empty()) + auto upload_report = std::make_unique<UploadReportMac>(); + + upload_report->file_path = LocateCrashReport(uuid, kReportStatePending); + if (upload_report->file_path.empty()) return kReportNotFound; - std::unique_ptr<UploadReport> upload_report(new UploadReport()); - upload_report->file_path = report_path; - - base::ScopedFD lock(ObtainReportLock(report_path)); + base::ScopedFD lock(ObtainReportLock(upload_report->file_path)); if (!lock.is_valid()) return kBusyError; - if (!ReadReportMetadataLocked(report_path, upload_report.get())) + if (!ReadReportMetadataLocked(upload_report->file_path, upload_report.get())) return kDatabaseError; - upload_report->lock_fd = lock.release(); - *report = upload_report.release(); + if (!upload_report->reader_->Open(upload_report->file_path)) { + return kFileSystemError; + } + + upload_report->database_ = this; + upload_report->lock_fd.reset(lock.release()); + report->reset(upload_report.release()); return kNoError; } CrashReportDatabase::OperationStatus -CrashReportDatabaseMac::RecordUploadAttempt(const Report* report, +CrashReportDatabaseMac::RecordUploadAttempt(UploadReport* report, bool successful, const std::string& id) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); @@ -479,13 +453,6 @@ if (report_path.empty()) return kReportNotFound; - std::unique_ptr<const UploadReport> upload_report( - static_cast<const UploadReport*>(report)); - - base::ScopedFD lock(upload_report->lock_fd); - if (!lock.is_valid()) - return kBusyError; - if (successful) { CrashReportDatabase::OperationStatus os = MarkReportCompletedLocked(report_path, &report_path); @@ -774,8 +741,6 @@ return std::unique_ptr<CrashReportDatabase>(database_mac.release()); } -} // namespace - // static std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize( const base::FilePath& path) {
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_test.cc b/third_party/crashpad/crashpad/client/crash_report_database_test.cc index c426696..55bcf3c 100644 --- a/third_party/crashpad/crashpad/client/crash_report_database_test.cc +++ b/third_party/crashpad/crashpad/client/crash_report_database_test.cc
@@ -19,8 +19,10 @@ #include "gtest/gtest.h" #include "test/errors.h" #include "test/file.h" +#include "test/filesystem.h" #include "test/scoped_temp_dir.h" #include "util/file/file_io.h" +#include "util/file/filesystem.h" namespace crashpad { namespace test { @@ -48,20 +50,19 @@ } void CreateCrashReport(CrashReportDatabase::Report* report) { - CrashReportDatabase::NewReport* new_report = nullptr; + std::unique_ptr<CrashReportDatabase::NewReport> new_report; ASSERT_EQ(db_->PrepareNewCrashReport(&new_report), CrashReportDatabase::kNoError); static constexpr char kTest[] = "test"; - ASSERT_TRUE(LoggingWriteFile(new_report->handle, kTest, sizeof(kTest))); + ASSERT_TRUE(new_report->Writer()->Write(kTest, sizeof(kTest))); UUID uuid; - EXPECT_EQ(db_->FinishedWritingCrashReport(new_report, &uuid), + EXPECT_EQ(db_->FinishedWritingCrashReport(std::move(new_report), &uuid), CrashReportDatabase::kNoError); EXPECT_EQ(db_->LookUpCrashReport(uuid, report), CrashReportDatabase::kNoError); ExpectPreparedCrashReport(*report); - ASSERT_TRUE(FileExists(report->file_path)); } void UploadReport(const UUID& uuid, bool successful, const std::string& id) { @@ -70,15 +71,19 @@ time_t times[2]; ASSERT_TRUE(settings->GetLastUploadAttemptTime(×[0])); - const CrashReportDatabase::Report* report = nullptr; + std::unique_ptr<const CrashReportDatabase::UploadReport> report; ASSERT_EQ(db_->GetReportForUploading(uuid, &report), CrashReportDatabase::kNoError); EXPECT_NE(report->uuid, UUID()); EXPECT_FALSE(report->file_path.empty()); EXPECT_TRUE(FileExists(report->file_path)) << report->file_path.value(); EXPECT_GT(report->creation_time, 0); - EXPECT_EQ(db_->RecordUploadAttempt(report, successful, id), - CrashReportDatabase::kNoError); + if (successful) { + EXPECT_EQ(db_->RecordUploadComplete(std::move(report), id), + CrashReportDatabase::kNoError); + } else { + report.reset(); + } ASSERT_TRUE(settings->GetLastUploadAttemptTime(×[1])); EXPECT_NE(times[1], 0); @@ -176,13 +181,12 @@ } TEST_F(CrashReportDatabaseTest, NewCrashReport) { - CrashReportDatabase::NewReport* new_report; + std::unique_ptr<CrashReportDatabase::NewReport> new_report; EXPECT_EQ(db()->PrepareNewCrashReport(&new_report), CrashReportDatabase::kNoError); - UUID expect_uuid = new_report->uuid; - EXPECT_TRUE(FileExists(new_report->path)) << new_report->path.value(); + UUID expect_uuid = new_report->ReportID(); UUID uuid; - EXPECT_EQ(db()->FinishedWritingCrashReport(new_report, &uuid), + EXPECT_EQ(db()->FinishedWritingCrashReport(std::move(new_report), &uuid), CrashReportDatabase::kNoError); EXPECT_EQ(uuid, expect_uuid); @@ -201,17 +205,6 @@ EXPECT_TRUE(reports.empty()); } -TEST_F(CrashReportDatabaseTest, ErrorWritingCrashReport) { - CrashReportDatabase::NewReport* new_report = nullptr; - ASSERT_EQ(db()->PrepareNewCrashReport(&new_report), - CrashReportDatabase::kNoError); - base::FilePath new_report_path = new_report->path; - EXPECT_TRUE(FileExists(new_report_path)) << new_report_path.value(); - EXPECT_EQ(db()->ErrorWritingCrashReport(new_report), - CrashReportDatabase::kNoError); - EXPECT_FALSE(FileExists(new_report_path)) << new_report_path.value(); -} - TEST_F(CrashReportDatabaseTest, LookUpCrashReport) { UUID uuid; @@ -465,16 +458,16 @@ CrashReportDatabase::Report report; CreateCrashReport(&report); - const CrashReportDatabase::Report* upload_report; + std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report; EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report), CrashReportDatabase::kNoError); - const CrashReportDatabase::Report* upload_report_2 = nullptr; + std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report_2; EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report_2), CrashReportDatabase::kBusyError); EXPECT_FALSE(upload_report_2); - EXPECT_EQ(db()->RecordUploadAttempt(upload_report, true, std::string()), + EXPECT_EQ(db()->RecordUploadComplete(std::move(upload_report), std::string()), CrashReportDatabase::kNoError); } @@ -482,25 +475,24 @@ CrashReportDatabase::Report report; CreateCrashReport(&report); - const CrashReportDatabase::Report* upload_report; + std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report; EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report), CrashReportDatabase::kNoError); - EXPECT_EQ(db()->RecordUploadAttempt(upload_report, true, std::string()), + EXPECT_EQ(db()->RecordUploadComplete(std::move(upload_report), std::string()), CrashReportDatabase::kNoError); - const CrashReportDatabase::Report* upload_report_2 = nullptr; + std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report_2; EXPECT_EQ(db()->GetReportForUploading(report.uuid, &upload_report_2), CrashReportDatabase::kReportNotFound); - EXPECT_FALSE(upload_report_2); + EXPECT_FALSE(upload_report_2.get()); } TEST_F(CrashReportDatabaseTest, MoveDatabase) { - CrashReportDatabase::NewReport* new_report; + std::unique_ptr<CrashReportDatabase::NewReport> new_report; EXPECT_EQ(db()->PrepareNewCrashReport(&new_report), CrashReportDatabase::kNoError); - EXPECT_TRUE(FileExists(new_report->path)) << new_report->path.value(); UUID uuid; - EXPECT_EQ(db()->FinishedWritingCrashReport(new_report, &uuid), + EXPECT_EQ(db()->FinishedWritingCrashReport(std::move(new_report), &uuid), CrashReportDatabase::kNoError); RelocateDatabase(); @@ -509,28 +501,22 @@ EXPECT_EQ(db()->LookUpCrashReport(uuid, &report), CrashReportDatabase::kNoError); ExpectPreparedCrashReport(report); - EXPECT_TRUE(FileExists(report.file_path)) << report.file_path.value(); } TEST_F(CrashReportDatabaseTest, ReportRemoved) { - CrashReportDatabase::NewReport* new_report; + std::unique_ptr<CrashReportDatabase::NewReport> new_report; EXPECT_EQ(db()->PrepareNewCrashReport(&new_report), CrashReportDatabase::kNoError); - EXPECT_TRUE(FileExists(new_report->path)) << new_report->path.value(); + UUID uuid; - EXPECT_EQ(db()->FinishedWritingCrashReport(new_report, &uuid), + EXPECT_EQ(db()->FinishedWritingCrashReport(std::move(new_report), &uuid), CrashReportDatabase::kNoError); CrashReportDatabase::Report report; EXPECT_EQ(db()->LookUpCrashReport(uuid, &report), CrashReportDatabase::kNoError); -#if defined(OS_WIN) - EXPECT_EQ(_wunlink(report.file_path.value().c_str()), 0); -#else - EXPECT_EQ(unlink(report.file_path.value().c_str()), 0) - << ErrnoMessage("unlink"); -#endif + EXPECT_TRUE(LoggingRemoveFile(report.file_path)); EXPECT_EQ(db()->LookUpCrashReport(uuid, &report), CrashReportDatabase::kReportNotFound); @@ -642,21 +628,21 @@ ASSERT_EQ(pending_reports.size(), 2u); // Check individual reports. - const CrashReportDatabase::Report* expicitly_requested_report; + const CrashReportDatabase::Report* explicitly_requested_report; const CrashReportDatabase::Report* pending_report; if (pending_reports[0].uuid == report_0_uuid) { pending_report = &pending_reports[0]; - expicitly_requested_report = &pending_reports[1]; + explicitly_requested_report = &pending_reports[1]; } else { pending_report = &pending_reports[1]; - expicitly_requested_report = &pending_reports[0]; + explicitly_requested_report = &pending_reports[0]; } EXPECT_EQ(pending_report->uuid, report_0_uuid); EXPECT_FALSE(pending_report->upload_explicitly_requested); - EXPECT_EQ(expicitly_requested_report->uuid, report_1_uuid); - EXPECT_TRUE(expicitly_requested_report->upload_explicitly_requested); + EXPECT_EQ(explicitly_requested_report->uuid, report_1_uuid); + EXPECT_TRUE(explicitly_requested_report->upload_explicitly_requested); // Explicitly requested reports will not have upload_explicitly_requested bit // after getting skipped. @@ -683,6 +669,76 @@ CrashReportDatabase::kCannotRequestUpload); } +// This test uses knowledge of the database format to break it, so it only +// applies to the unfified database implementation. +#if !defined(OS_MACOSX) && !defined(OS_WIN) +TEST_F(CrashReportDatabaseTest, CleanBrokenDatabase) { + // Remove report files if metadata goes missing. + CrashReportDatabase::Report report; + ASSERT_NO_FATAL_FAILURE(CreateCrashReport(&report)); + + const base::FilePath metadata( + report.file_path.RemoveFinalExtension().value() + + FILE_PATH_LITERAL(".meta")); + ASSERT_TRUE(PathExists(report.file_path)); + ASSERT_TRUE(PathExists(metadata)); + + ASSERT_TRUE(LoggingRemoveFile(metadata)); + EXPECT_EQ(db()->CleanDatabase(0), 1); + + EXPECT_FALSE(PathExists(report.file_path)); + EXPECT_FALSE(PathExists(metadata)); + + // Remove metadata files if reports go missing. + ASSERT_NO_FATAL_FAILURE(CreateCrashReport(&report)); + const base::FilePath metadata2( + report.file_path.RemoveFinalExtension().value() + + FILE_PATH_LITERAL(".meta")); + ASSERT_TRUE(PathExists(report.file_path)); + ASSERT_TRUE(PathExists(metadata2)); + + ASSERT_TRUE(LoggingRemoveFile(report.file_path)); + EXPECT_EQ(db()->CleanDatabase(0), 1); + + EXPECT_FALSE(PathExists(report.file_path)); + EXPECT_FALSE(PathExists(metadata2)); + + // Remove stale new files. + std::unique_ptr<CrashReportDatabase::NewReport> new_report; + EXPECT_EQ(db()->PrepareNewCrashReport(&new_report), + CrashReportDatabase::kNoError); + new_report->Writer()->Close(); + EXPECT_EQ(db()->CleanDatabase(0), 1); + + // Remove stale lock files and their associated reports. + ASSERT_NO_FATAL_FAILURE(CreateCrashReport(&report)); + const base::FilePath metadata3( + report.file_path.RemoveFinalExtension().value() + + FILE_PATH_LITERAL(".meta")); + ASSERT_TRUE(PathExists(report.file_path)); + ASSERT_TRUE(PathExists(metadata3)); + + const base::FilePath lockpath( + report.file_path.RemoveFinalExtension().value() + + FILE_PATH_LITERAL(".lock")); + ScopedFileHandle handle(LoggingOpenFileForWrite( + lockpath, FileWriteMode::kCreateOrFail, FilePermissions::kOwnerOnly)); + ASSERT_TRUE(handle.is_valid()); + + time_t expired_timestamp = time(nullptr) - 60 * 60 * 24 * 3; + + ASSERT_TRUE(LoggingWriteFile( + handle.get(), &expired_timestamp, sizeof(expired_timestamp))); + ASSERT_TRUE(LoggingCloseFile(handle.get())); + ignore_result(handle.release()); + + EXPECT_EQ(db()->CleanDatabase(0), 1); + + EXPECT_FALSE(PathExists(report.file_path)); + EXPECT_FALSE(PathExists(metadata3)); +} +#endif // !OS_MACOSX && !OS_WIN + } // namespace } // namespace test } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/crash_report_database_win.cc b/third_party/crashpad/crashpad/client/crash_report_database_win.cc index 538eff5f..fb3cd8f 100644 --- a/third_party/crashpad/crashpad/client/crash_report_database_win.cc +++ b/third_party/crashpad/crashpad/client/crash_report_database_win.cc
@@ -29,6 +29,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "client/settings.h" +#include "util/misc/implicit_cast.h" #include "util/misc/initialization_state_dcheck.h" #include "util/misc/metrics.h" @@ -571,6 +572,8 @@ return EnsureDirectory(path); } +} // namespace + // CrashReportDatabaseWin ------------------------------------------------------ class CrashReportDatabaseWin : public CrashReportDatabase { @@ -582,24 +585,27 @@ // CrashReportDatabase: Settings* GetSettings() override; - OperationStatus PrepareNewCrashReport(NewReport** report) override; - OperationStatus FinishedWritingCrashReport(NewReport* report, + OperationStatus PrepareNewCrashReport( + std::unique_ptr<NewReport>* report) override; + OperationStatus FinishedWritingCrashReport(std::unique_ptr<NewReport> report, UUID* uuid) override; - OperationStatus ErrorWritingCrashReport(NewReport* report) override; OperationStatus LookUpCrashReport(const UUID& uuid, Report* report) override; OperationStatus GetPendingReports(std::vector<Report>* reports) override; OperationStatus GetCompletedReports(std::vector<Report>* reports) override; - OperationStatus GetReportForUploading(const UUID& uuid, - const Report** report) override; - OperationStatus RecordUploadAttempt(const Report* report, - bool successful, - const std::string& id) override; + OperationStatus GetReportForUploading( + const UUID& uuid, + std::unique_ptr<const UploadReport>* report) override; OperationStatus SkipReportUpload(const UUID& uuid, Metrics::CrashSkippedReason reason) override; OperationStatus DeleteReport(const UUID& uuid) override; OperationStatus RequestUpload(const UUID& uuid) override; private: + // CrashReportDatabase: + OperationStatus RecordUploadAttempt(UploadReport* report, + bool successful, + const std::string& id) override; + std::unique_ptr<Metadata> AcquireMetadata(); base::FilePath base_dir_; @@ -610,11 +616,7 @@ }; CrashReportDatabaseWin::CrashReportDatabaseWin(const base::FilePath& path) - : CrashReportDatabase(), - base_dir_(path), - settings_(base_dir_.Append(kSettings)), - initialized_() { -} + : CrashReportDatabase(), base_dir_(path), settings_(), initialized_() {} CrashReportDatabaseWin::~CrashReportDatabaseWin() { } @@ -634,7 +636,7 @@ if (!CreateDirectoryIfNecessary(base_dir_.Append(kReportsDirectory))) return false; - if (!settings_.Initialize()) + if (!settings_.Initialize(base_dir_.Append(kSettings))) return false; INITIALIZATION_STATE_SET_VALID(initialized_); @@ -647,67 +649,38 @@ } OperationStatus CrashReportDatabaseWin::PrepareNewCrashReport( - NewReport** report) { + std::unique_ptr<NewReport>* report) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::unique_ptr<NewReport> new_report(new NewReport()); - if (!new_report->uuid.InitializeWithNew()) + if (!new_report->Initialize(base_dir_.Append(kReportsDirectory), + std::wstring(L".") + kCrashReportFileExtension)) { return kFileSystemError; - new_report->path = base_dir_.Append(kReportsDirectory) - .Append(new_report->uuid.ToString16() + L"." + - kCrashReportFileExtension); - new_report->handle = LoggingOpenFileForWrite(new_report->path, - FileWriteMode::kCreateOrFail, - FilePermissions::kOwnerOnly); - if (new_report->handle == INVALID_HANDLE_VALUE) - return kFileSystemError; + } - *report = new_report.release(); + report->reset(new_report.release()); return kNoError; } OperationStatus CrashReportDatabaseWin::FinishedWritingCrashReport( - NewReport* report, + std::unique_ptr<NewReport> report, UUID* uuid) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); - // Take ownership of the report. - std::unique_ptr<NewReport> scoped_report(report); - // Take ownership of the file handle. - ScopedFileHandle handle(report->handle); - std::unique_ptr<Metadata> metadata(AcquireMetadata()); if (!metadata) return kDatabaseError; - metadata->AddNewRecord(ReportDisk(scoped_report->uuid, - scoped_report->path, + metadata->AddNewRecord(ReportDisk(report->ReportID(), + report->file_remover_.get(), time(nullptr), ReportState::kPending)); - *uuid = scoped_report->uuid; + + ignore_result(report->file_remover_.release()); + + *uuid = report->ReportID(); Metrics::CrashReportPending(Metrics::PendingReportReason::kNewlyCreated); - Metrics::CrashReportSize(handle.get()); - - return kNoError; -} - -OperationStatus CrashReportDatabaseWin::ErrorWritingCrashReport( - NewReport* report) { - INITIALIZATION_STATE_DCHECK_VALID(initialized_); - - // Take ownership of the report. - std::unique_ptr<NewReport> scoped_report(report); - - // Close the outstanding handle. - LoggingCloseFile(report->handle); - - // We failed to write, so remove the dump file. There's no entry in the - // metadata table yet. - if (!DeleteFile(scoped_report->path.value().c_str())) { - PLOG(ERROR) << "DeleteFile " - << base::UTF16ToUTF8(scoped_report->path.value()); - return kFileSystemError; - } + Metrics::CrashReportSize(report->Writer()->Seek(0, SEEK_END)); return kNoError; } @@ -747,44 +720,38 @@ OperationStatus CrashReportDatabaseWin::GetReportForUploading( const UUID& uuid, - const Report** report) { + std::unique_ptr<const UploadReport>* report) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::unique_ptr<Metadata> metadata(AcquireMetadata()); if (!metadata) return kDatabaseError; - // TODO(scottmg): After returning this report to the client, there is no way - // to reap this report if the uploader fails to call RecordUploadAttempt() or - // SkipReportUpload() (if it crashed or was otherwise buggy). To resolve this, - // one possibility would be to change the interface to be FileHandle based, so - // that instead of giving the file_path back to the client and changing state - // to kUploading, we return an exclusive access handle, and use that as the - // signal that the upload is pending, rather than an update to state in the - // metadata. Alternatively, there could be a "garbage collection" at startup - // where any reports that are orphaned in the kUploading state are either - // reset to kPending to retry, or discarded. + ReportDisk* report_disk; OperationStatus os = metadata->FindSingleReportAndMarkDirty( uuid, ReportState::kPending, &report_disk); if (os == kNoError) { report_disk->state = ReportState::kUploading; - // Create a copy for passing back to client. This will be freed in - // RecordUploadAttempt. - *report = new Report(*report_disk); + auto upload_report = std::make_unique<UploadReport>(); + *implicit_cast<Report*>(upload_report.get()) = *report_disk; + + if (!upload_report->Initialize(upload_report->file_path, this)) { + return kFileSystemError; + } + + report->reset(upload_report.release()); } return os; } OperationStatus CrashReportDatabaseWin::RecordUploadAttempt( - const Report* report, + UploadReport* report, bool successful, const std::string& id) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); Metrics::CrashUploadAttempted(successful); - // Take ownership, allocated in GetReportForUploading. - std::unique_ptr<const Report> upload_report(report); std::unique_ptr<Metadata> metadata(AcquireMetadata()); if (!metadata) return kDatabaseError; @@ -903,8 +870,6 @@ return kNoError; } -} // namespace - // static std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize( const base::FilePath& path) {
diff --git a/third_party/crashpad/crashpad/client/crashpad_client.h b/third_party/crashpad/crashpad/client/crashpad_client.h index 7cf2eb8..3cd806a1 100644 --- a/third_party/crashpad/crashpad/client/crashpad_client.h +++ b/third_party/crashpad/crashpad/client/crashpad_client.h
@@ -24,12 +24,16 @@ #include "base/files/file_path.h" #include "base/macros.h" #include "build/build_config.h" +#include "util/misc/capture_context.h" #if defined(OS_MACOSX) #include "base/mac/scoped_mach_port.h" #elif defined(OS_WIN) #include <windows.h> #include "util/win/scoped_handle.h" +#elif defined(OS_LINUX) || defined(OS_ANDROID) +#include <signal.h> +#include <ucontext.h> #endif namespace crashpad { @@ -168,6 +172,40 @@ const std::map<std::string, std::string>& annotations, const std::vector<std::string>& arguments, int socket); + + //! \brief Requests that the handler capture a dump even though there hasn't + //! been a crash. + //! + //! A handler must have already been installed before calling this method. + //! + //! TODO(jperaza): Floating point information in the context is zeroed out + //! until CaptureContext() supports collecting that information. + //! + //! \param[in] context A NativeCPUContext, generally captured by + //! CaptureContext() or similar. + static void DumpWithoutCrash(NativeCPUContext* context); + + //! \brief The type for custom handlers installed by clients. + using FirstChanceHandler = bool (*)(int, siginfo_t*, ucontext_t*); + + //! \brief Installs a custom crash signal handler which runs before the + //! currently installed Crashpad handler. + //! + //! Handling signals appropriately can be tricky and use of this method + //! should be avoided, if possible. + //! + //! A handler must have already been installed before calling this method. + //! + //! The custom handler runs in a signal handler context and must be safe for + //! that purpose. + //! + //! If the custom handler returns `true`, the signal is considered handled and + //! the signal handler returns. Otherwise, the currently installed Crashpad + //! signal handler is run. + //! + //! \param[in] handler The custom crash signal handler to install. + static void SetFirstChanceExceptionHandler(FirstChanceHandler handler); + #endif // OS_LINUX || OS_ANDROID || DOXYGEN #if defined(OS_MACOSX) || DOXYGEN
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc index a36d922..ca13c29 100644 --- a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc +++ b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
@@ -27,6 +27,7 @@ #include "util/file/file_io.h" #include "util/linux/exception_handler_client.h" #include "util/linux/exception_information.h" +#include "util/linux/scoped_pr_set_ptracer.h" #include "util/misc/from_pointer_cast.h" #include "util/posix/double_fork_and_exec.h" #include "util/posix/signals.h" @@ -82,7 +83,7 @@ } } -void ConvertArgvStrings(const std::vector<std::string> argv_strings, +void ConvertArgvStrings(const std::vector<std::string>& argv_strings, std::vector<const char*>* argv) { argv->clear(); argv->reserve(argv_strings.size() + 1); @@ -92,8 +93,28 @@ argv->push_back(nullptr); } +class SignalHandler { + public: + virtual void HandleCrashFatal(int signo, + siginfo_t* siginfo, + void* context) = 0; + virtual bool HandleCrashNonFatal(int signo, + siginfo_t* siginfo, + void* context) = 0; + + void SetFirstChanceHandler(CrashpadClient::FirstChanceHandler handler) { + first_chance_handler_ = handler; + } + + protected: + SignalHandler() = default; + ~SignalHandler() = default; + + CrashpadClient::FirstChanceHandler first_chance_handler_ = nullptr; +}; + // Launches a single use handler to snapshot this process. -class LaunchAtCrashHandler { +class LaunchAtCrashHandler : public SignalHandler { public: static LaunchAtCrashHandler* Get() { static LaunchAtCrashHandler* instance = new LaunchAtCrashHandler(); @@ -110,6 +131,46 @@ return Signals::InstallCrashHandlers(HandleCrash, 0, nullptr); } + bool HandleCrashNonFatal(int signo, + siginfo_t* siginfo, + void* context) override { + if (first_chance_handler_ && + first_chance_handler_( + signo, siginfo, static_cast<ucontext_t*>(context))) { + return true; + } + + exception_information_.siginfo_address = + FromPointerCast<decltype(exception_information_.siginfo_address)>( + siginfo); + exception_information_.context_address = + FromPointerCast<decltype(exception_information_.context_address)>( + context); + exception_information_.thread_id = syscall(SYS_gettid); + + ScopedPrSetPtracer set_ptracer(getpid(), /* may_log= */ false); + + pid_t pid = fork(); + if (pid < 0) { + return false; + } + if (pid == 0) { + execv(argv_[0], const_cast<char* const*>(argv_.data())); + _exit(EXIT_FAILURE); + } + + int status; + waitpid(pid, &status, 0); + return false; + } + + void HandleCrashFatal(int signo, siginfo_t* siginfo, void* context) override { + if (HandleCrashNonFatal(signo, siginfo, context)) { + return; + } + Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, nullptr); + } + private: LaunchAtCrashHandler() = default; @@ -117,27 +178,7 @@ static void HandleCrash(int signo, siginfo_t* siginfo, void* context) { auto state = Get(); - auto exception_information = &state->exception_information_; - - exception_information->siginfo_address = - FromPointerCast<decltype(exception_information->siginfo_address)>( - siginfo); - exception_information->context_address = - FromPointerCast<decltype(exception_information->context_address)>( - context); - exception_information->thread_id = syscall(SYS_gettid); - - pid_t pid = fork(); - if (pid < 0) { - return; - } - if (pid == 0) { - execv(state->argv_[0], const_cast<char* const*>(state->argv_.data())); - return; - } - - int status; - waitpid(pid, &status, 0); + state->HandleCrashFatal(signo, siginfo, context); } std::vector<std::string> argv_strings_; @@ -147,6 +188,11 @@ DISALLOW_COPY_AND_ASSIGN(LaunchAtCrashHandler); }; +// A pointer to the currently installed crash signal handler. This allows +// the static method CrashpadClient::DumpWithoutCrashing to simulate a crash +// using the currently configured crash handling strategy. +static SignalHandler* g_crash_handler; + } // namespace CrashpadClient::CrashpadClient() {} @@ -181,7 +227,12 @@ handler, database, metrics_dir, url, annotations, arguments, &argv); auto signal_handler = LaunchAtCrashHandler::Get(); - return signal_handler->Initialize(&argv); + if (signal_handler->Initialize(&argv)) { + DCHECK(!g_crash_handler); + g_crash_handler = signal_handler; + return true; + } + return false; } bool CrashpadClient::StartHandlerForClient( @@ -201,4 +252,38 @@ return DoubleForkAndExec(argv, socket, true, nullptr); } +// static +void CrashpadClient::DumpWithoutCrash(NativeCPUContext* context) { + DCHECK(g_crash_handler); + +#if defined(ARCH_CPU_X86) + memset(&context->__fpregs_mem, 0, sizeof(context->__fpregs_mem)); + context->__fpregs_mem.status = 0xffff0000; +#elif defined(ARCH_CPU_X86_64) + memset(&context->__fpregs_mem, 0, sizeof(context->__fpregs_mem)); +#elif defined(ARCH_CPU_ARMEL) + memset(context->uc_regspace, 0, sizeof(context->uc_regspace)); +#elif defined(ARCH_CPU_ARM64) + memset(context->uc_mcontext.__reserved, + 0, + sizeof(context->uc_mcontext.__reserved)); +#else +#error Port. +#endif + + siginfo_t siginfo; + siginfo.si_signo = Signals::kSimulatedSigno; + siginfo.si_errno = 0; + siginfo.si_code = 0; + g_crash_handler->HandleCrashNonFatal( + siginfo.si_signo, &siginfo, reinterpret_cast<void*>(context)); +} + +// static +void CrashpadClient::SetFirstChanceExceptionHandler( + FirstChanceHandler handler) { + DCHECK(g_crash_handler); + g_crash_handler->SetFirstChanceHandler(handler); +} + } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_linux_test.cc b/third_party/crashpad/crashpad/client/crashpad_client_linux_test.cc new file mode 100644 index 0000000..9610cdd --- /dev/null +++ b/third_party/crashpad/crashpad/client/crashpad_client_linux_test.cc
@@ -0,0 +1,327 @@ +// Copyright 2018 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 "client/crashpad_client.h" + +#include <stdlib.h> +#include <sys/socket.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <unistd.h> + +#include "base/logging.h" +#include "client/crash_report_database.h" +#include "client/simulate_crash.h" +#include "gtest/gtest.h" +#include "test/multiprocess_exec.h" +#include "test/multiprocess.h" +#include "test/scoped_temp_dir.h" +#include "test/test_paths.h" +#include "util/file/file_io.h" +#include "util/linux/exception_handler_client.h" +#include "util/linux/exception_information.h" +#include "util/misc/address_types.h" +#include "util/misc/from_pointer_cast.h" +#include "util/posix/signals.h" + +namespace crashpad { +namespace test { +namespace { + +bool HandleCrashSuccessfully(int, siginfo_t*, ucontext_t*) { + return true; +} + +TEST(CrashpadClient, SimulateCrash) { + ScopedTempDir temp_dir; + + base::FilePath handler_path = TestPaths::Executable().DirName().Append( + FILE_PATH_LITERAL("crashpad_handler")); + + crashpad::CrashpadClient client; + ASSERT_TRUE(client.StartHandlerAtCrash(handler_path, + base::FilePath(temp_dir.path()), + base::FilePath(), + "", + std::map<std::string, std::string>(), + std::vector<std::string>())); + + auto database = + CrashReportDatabase::InitializeWithoutCreating(temp_dir.path()); + ASSERT_TRUE(database); + + { + CrashpadClient::SetFirstChanceExceptionHandler(HandleCrashSuccessfully); + + CRASHPAD_SIMULATE_CRASH(); + + std::vector<CrashReportDatabase::Report> reports; + ASSERT_EQ(database->GetPendingReports(&reports), + CrashReportDatabase::kNoError); + EXPECT_EQ(reports.size(), 0u); + + reports.clear(); + ASSERT_EQ(database->GetCompletedReports(&reports), + CrashReportDatabase::kNoError); + EXPECT_EQ(reports.size(), 0u); + } + + { + CrashpadClient::SetFirstChanceExceptionHandler(nullptr); + + CRASHPAD_SIMULATE_CRASH(); + + std::vector<CrashReportDatabase::Report> reports; + ASSERT_EQ(database->GetPendingReports(&reports), + CrashReportDatabase::kNoError); + EXPECT_EQ(reports.size(), 0u); + + reports.clear(); + ASSERT_EQ(database->GetCompletedReports(&reports), + CrashReportDatabase::kNoError); + EXPECT_EQ(reports.size(), 1u); + } +} + +CRASHPAD_CHILD_TEST_MAIN(StartHandlerAtCrashChild) { + FileHandle in = StdioFileHandle(StdioStream::kStandardInput); + + VMSize temp_dir_length; + CheckedReadFileExactly(in, &temp_dir_length, sizeof(temp_dir_length)); + + std::string temp_dir(temp_dir_length, '\0'); + CheckedReadFileExactly(in, &temp_dir[0], temp_dir_length); + + base::FilePath handler_path = TestPaths::Executable().DirName().Append( + FILE_PATH_LITERAL("crashpad_handler")); + + crashpad::CrashpadClient client; + if (!client.StartHandlerAtCrash(handler_path, + base::FilePath(temp_dir), + base::FilePath(), + "", + std::map<std::string, std::string>(), + std::vector<std::string>())) { + return EXIT_FAILURE; + } + + __builtin_trap(); + + NOTREACHED(); + return EXIT_SUCCESS; +} + +class StartHandlerAtCrashTest : public MultiprocessExec { + public: + StartHandlerAtCrashTest() : MultiprocessExec() { + SetChildTestMainFunction("StartHandlerAtCrashChild"); + SetExpectedChildTerminationBuiltinTrap(); + } + + private: + void MultiprocessParent() override { + ScopedTempDir temp_dir; + VMSize temp_dir_length = temp_dir.path().value().size(); + ASSERT_TRUE(LoggingWriteFile( + WritePipeHandle(), &temp_dir_length, sizeof(temp_dir_length))); + ASSERT_TRUE(LoggingWriteFile( + WritePipeHandle(), temp_dir.path().value().data(), temp_dir_length)); + + // Wait for child to finish. + CheckedReadFileAtEOF(ReadPipeHandle()); + + auto database = CrashReportDatabase::Initialize(temp_dir.path()); + ASSERT_TRUE(database); + + std::vector<CrashReportDatabase::Report> reports; + ASSERT_EQ(database->GetPendingReports(&reports), + CrashReportDatabase::kNoError); + EXPECT_EQ(reports.size(), 0u); + + ASSERT_EQ(database->GetCompletedReports(&reports), + CrashReportDatabase::kNoError); + EXPECT_EQ(reports.size(), 1u); + } + + DISALLOW_COPY_AND_ASSIGN(StartHandlerAtCrashTest); +}; + +TEST(CrashpadClient, StartHandlerAtCrash) { + StartHandlerAtCrashTest test; + test.Run(); +} + +// Test state for starting the handler for another process. +class StartHandlerForClientTest { + public: + StartHandlerForClientTest() = default; + ~StartHandlerForClientTest() = default; + + bool Initialize() { + int socks[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) != 0) { + PLOG(ERROR) << "socketpair"; + return false; + } + client_sock_.reset(socks[0]); + server_sock_.reset(socks[1]); + + return true; + } + + bool StartHandlerOnDemand() { + char c; + if (!LoggingReadFileExactly(server_sock_.get(), &c, sizeof(c))) { + ADD_FAILURE(); + return false; + } + + base::FilePath handler_path = TestPaths::Executable().DirName().Append( + FILE_PATH_LITERAL("crashpad_handler")); + + CrashpadClient client; + if (!client.StartHandlerForClient(handler_path, + temp_dir_.path(), + base::FilePath(), + "", + std::map<std::string, std::string>(), + std::vector<std::string>(), + server_sock_.get())) { + ADD_FAILURE(); + return false; + } + + return true; + } + + void ExpectReport() { + auto database = + CrashReportDatabase::InitializeWithoutCreating(temp_dir_.path()); + ASSERT_TRUE(database); + + std::vector<CrashReportDatabase::Report> reports; + ASSERT_EQ(database->GetPendingReports(&reports), + CrashReportDatabase::kNoError); + EXPECT_EQ(reports.size(), 0u); + + ASSERT_EQ(database->GetCompletedReports(&reports), + CrashReportDatabase::kNoError); + EXPECT_EQ(reports.size(), 1u); + } + + bool InstallHandler() { + auto signal_handler = SandboxedHandler::Get(); + return signal_handler->Initialize(client_sock_.get()); + } + + private: + // A signal handler that defers handler process startup to another, presumably + // more privileged, process. + class SandboxedHandler { + public: + static SandboxedHandler* Get() { + static SandboxedHandler* instance = new SandboxedHandler(); + return instance; + } + + bool Initialize(FileHandle client_sock) { + client_sock_ = client_sock; + return Signals::InstallCrashHandlers(HandleCrash, 0, nullptr); + } + + private: + SandboxedHandler() = default; + ~SandboxedHandler() = delete; + + static void HandleCrash(int signo, siginfo_t* siginfo, void* context) { + auto state = Get(); + + char c; + CHECK(LoggingWriteFile(state->client_sock_, &c, sizeof(c))); + + ExceptionInformation exception_information; + exception_information.siginfo_address = + FromPointerCast<decltype(exception_information.siginfo_address)>( + siginfo); + exception_information.context_address = + FromPointerCast<decltype(exception_information.context_address)>( + context); + exception_information.thread_id = syscall(SYS_gettid); + + ClientInformation info = {}; + info.exception_information_address = + FromPointerCast<decltype(info.exception_information_address)>( + &exception_information); + + ExceptionHandlerClient handler_client(state->client_sock_); + CHECK_EQ(handler_client.RequestCrashDump(info), 0); + + Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, nullptr); + } + + FileHandle client_sock_; + + DISALLOW_COPY_AND_ASSIGN(SandboxedHandler); + }; + + ScopedTempDir temp_dir_; + ScopedFileHandle client_sock_; + ScopedFileHandle server_sock_; + + DISALLOW_COPY_AND_ASSIGN(StartHandlerForClientTest); +}; + +// Tests starting the handler for a child process. +class StartHandlerForChildTest : public Multiprocess { + public: + StartHandlerForChildTest() = default; + ~StartHandlerForChildTest() = default; + + bool Initialize() { + SetExpectedChildTerminationBuiltinTrap(); + return test_state_.Initialize(); + } + + private: + void MultiprocessParent() { + ASSERT_TRUE(test_state_.StartHandlerOnDemand()); + + // Wait for chlid to finish. + CheckedReadFileAtEOF(ReadPipeHandle()); + + test_state_.ExpectReport(); + } + + void MultiprocessChild() { + CHECK(test_state_.InstallHandler()); + + __builtin_trap(); + + NOTREACHED(); + } + + StartHandlerForClientTest test_state_; + + DISALLOW_COPY_AND_ASSIGN(StartHandlerForChildTest); +}; + +TEST(CrashpadClient, StartHandlerForChild) { + StartHandlerForChildTest test; + ASSERT_TRUE(test.Initialize()); + test.Run(); +} + +} // namespace +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_win.cc b/third_party/crashpad/crashpad/client/crashpad_client_win.cc index dd25c9e..8ceded3 100644 --- a/third_party/crashpad/crashpad/client/crashpad_client_win.cc +++ b/third_party/crashpad/crashpad/client/crashpad_client_win.cc
@@ -30,10 +30,10 @@ #include "base/strings/utf_string_conversions.h" #include "base/synchronization/lock.h" #include "util/file/file_io.h" +#include "util/misc/capture_context.h" #include "util/misc/from_pointer_cast.h" #include "util/misc/random_string.h" #include "util/win/address_types.h" -#include "util/win/capture_context.h" #include "util/win/command_line.h" #include "util/win/critical_section_with_debug_info.h" #include "util/win/get_function.h"
diff --git a/third_party/crashpad/crashpad/client/crashpad_info.cc b/third_party/crashpad/crashpad/client/crashpad_info.cc index b545a3c..7c1316e 100644 --- a/third_party/crashpad/crashpad/client/crashpad_info.cc +++ b/third_party/crashpad/crashpad/client/crashpad_info.cc
@@ -52,12 +52,6 @@ // because it’s POD, no code should need to run to initialize this under // release-mode optimization. -// Platforms that use ELF objects need to locate this structure via the dynamic -// symbol table, so avoid name mangling. -#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA) -extern "C" { -#endif - #if defined(OS_POSIX) __attribute__(( @@ -65,10 +59,6 @@ // Put the structure in a well-known section name where it can be easily // found without having to consult the symbol table. section(SEG_DATA ",crashpad_info"), - - // There's no need to expose this as a public symbol from the symbol table. - // All accesses from the outside can locate the well-known section name. - visibility("hidden"), #endif #if defined(ADDRESS_SANITIZER) @@ -80,6 +70,10 @@ aligned(64), #endif // defined(ADDRESS_SANITIZER) + // There's no need to expose this as a public symbol from the symbol table. + // All accesses from the outside can locate the well-known section name. + visibility("hidden"), + // The “used” attribute prevents the structure from being dead-stripped. used)) @@ -96,12 +90,19 @@ CrashpadInfo g_crashpad_info; -#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA) -} // extern "C" -#endif +extern "C" int* CRASHPAD_NOTE_REFERENCE; // static CrashpadInfo* CrashpadInfo::GetCrashpadInfo() { +#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA) + // This otherwise-unused reference is used so that any module that + // references GetCrashpadInfo() will also include the note in the + // .note.crashpad.info section. That note in turn contains the address of + // g_crashpad_info. This allows the module reader to find the CrashpadInfo + // structure without requiring the use of the dynamic symbol table. + static volatile int* pointer_to_note_section = CRASHPAD_NOTE_REFERENCE; + (void)pointer_to_note_section; +#endif return &g_crashpad_info; }
diff --git a/third_party/crashpad/crashpad/client/crashpad_info_note.S b/third_party/crashpad/crashpad/client/crashpad_info_note.S new file mode 100644 index 0000000..8084db9 --- /dev/null +++ b/third_party/crashpad/crashpad/client/crashpad_info_note.S
@@ -0,0 +1,60 @@ +// Copyright 2018 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. + +// This note section is used on ELF platforms to give ElfImageReader a method +// of finding the instance of CrashpadInfo g_crashpad_info without requiring +// that symbol to be in the dynamic symbol table. + +#include "build/build_config.h" +#include "util/misc/elf_note_types.h" + +// namespace crashpad { +// CrashpadInfo g_crashpad_info; +// } // namespace crashpad +#define CRASHPAD_INFO_SYMBOL _ZN8crashpad15g_crashpad_infoE + +#define NOTE_ALIGN 4 + + // This section must be "a"llocated so that it appears in the final binary at + // runtime, and "w"ritable so that the relocation to CRASHPAD_INFO_SYMBOL can + // be performed. + .section .note.crashpad.info,"aw",%note + .balign NOTE_ALIGN + # .globl indicates that it's available to link against other .o files. .hidden + # indicates that it will not appear in the executable's symbol table. + .globl CRASHPAD_NOTE_REFERENCE + .hidden CRASHPAD_NOTE_REFERENCE + .type CRASHPAD_NOTE_REFERENCE, %object +CRASHPAD_NOTE_REFERENCE: + .long name_end - name // namesz + .long desc_end - desc // descsz + .long CRASHPAD_ELF_NOTE_TYPE_CRASHPAD_INFO // type +name: + .asciz CRASHPAD_ELF_NOTE_NAME +name_end: + .balign NOTE_ALIGN +desc: +#if defined(ARCH_CPU_64_BITS) + .quad CRASHPAD_INFO_SYMBOL +#else +#if defined(ARCH_CPU_LITTLE_ENDIAN) + .long CRASHPAD_INFO_SYMBOL + .long 0 +#else + .long 0 + .long CRASHPAD_INFO_SYMBOL +#endif // ARCH_CPU_LITTLE_ENDIAN +#endif // ARCH_CPU_64_BITS +desc_end: + .size CRASHPAD_NOTE_REFERENCE, .-CRASHPAD_NOTE_REFERENCE
diff --git a/third_party/crashpad/crashpad/client/prune_crash_reports_test.cc b/third_party/crashpad/crashpad/client/prune_crash_reports_test.cc index 54d6941e..2648dee 100644 --- a/third_party/crashpad/crashpad/client/prune_crash_reports_test.cc +++ b/third_party/crashpad/crashpad/client/prune_crash_reports_test.cc
@@ -36,20 +36,27 @@ public: // CrashReportDatabase: MOCK_METHOD0(GetSettings, Settings*()); - MOCK_METHOD1(PrepareNewCrashReport, OperationStatus(NewReport**)); - MOCK_METHOD2(FinishedWritingCrashReport, OperationStatus(NewReport*, UUID*)); - MOCK_METHOD1(ErrorWritingCrashReport, OperationStatus(NewReport*)); + MOCK_METHOD1(PrepareNewCrashReport, + OperationStatus(std::unique_ptr<NewReport>*)); MOCK_METHOD2(LookUpCrashReport, OperationStatus(const UUID&, Report*)); MOCK_METHOD1(GetPendingReports, OperationStatus(std::vector<Report>*)); MOCK_METHOD1(GetCompletedReports, OperationStatus(std::vector<Report>*)); MOCK_METHOD2(GetReportForUploading, - OperationStatus(const UUID&, const Report**)); + OperationStatus(const UUID&, + std::unique_ptr<const UploadReport>*)); MOCK_METHOD3(RecordUploadAttempt, - OperationStatus(const Report*, bool, const std::string&)); + OperationStatus(UploadReport*, bool, const std::string&)); MOCK_METHOD2(SkipReportUpload, OperationStatus(const UUID&, Metrics::CrashSkippedReason)); MOCK_METHOD1(DeleteReport, OperationStatus(const UUID&)); MOCK_METHOD1(RequestUpload, OperationStatus(const UUID&)); + + // gmock doesn't support mocking methods with non-copyable types such as + // unique_ptr. + OperationStatus FinishedWritingCrashReport(std::unique_ptr<NewReport> report, + UUID* uuid) override { + return kNoError; + } }; time_t NDaysAgo(int num_days) {
diff --git a/third_party/crashpad/crashpad/client/settings.cc b/third_party/crashpad/crashpad/client/settings.cc index 15d16f2..20bd258 100644 --- a/third_party/crashpad/crashpad/client/settings.cc +++ b/third_party/crashpad/crashpad/client/settings.cc
@@ -20,10 +20,55 @@ #include "base/logging.h" #include "base/posix/eintr_wrapper.h" +#include "util/file/filesystem.h" #include "util/numeric/in_range_cast.h" namespace crashpad { +#if defined(OS_FUCHSIA) + +Settings::ScopedLockedFileHandle::ScopedLockedFileHandle() + : handle_(kInvalidFileHandle), lockfile_path_() { + } + +Settings::ScopedLockedFileHandle::ScopedLockedFileHandle( + FileHandle handle, + const base::FilePath& lockfile_path) + : handle_(handle), lockfile_path_(lockfile_path) { +} + +Settings::ScopedLockedFileHandle::ScopedLockedFileHandle( + ScopedLockedFileHandle&& other) + : handle_(other.handle_), lockfile_path_(other.lockfile_path_) { + other.handle_ = kInvalidFileHandle; + other.lockfile_path_ = base::FilePath(); +} + +Settings::ScopedLockedFileHandle& Settings::ScopedLockedFileHandle::operator=( + ScopedLockedFileHandle&& other) { + handle_ = other.handle_; + lockfile_path_ = other.lockfile_path_; + + other.handle_ = kInvalidFileHandle; + other.lockfile_path_ = base::FilePath(); + return *this; +} + +Settings::ScopedLockedFileHandle::~ScopedLockedFileHandle() { + Destroy(); +} + +void Settings::ScopedLockedFileHandle::Destroy() { + if (handle_ != kInvalidFileHandle) { + CheckedCloseFile(handle_); + } + if (!lockfile_path_.empty()) { + DCHECK(LoggingRemoveFile(lockfile_path_)); + } +} + +#else // OS_FUCHSIA + namespace internal { // static @@ -36,6 +81,8 @@ } // namespace internal +#endif // OS_FUCHSIA + struct Settings::Data { static const uint32_t kSettingsMagic = 'CPds'; static const uint32_t kSettingsVersion = 1; @@ -59,16 +106,14 @@ UUID client_id; }; -Settings::Settings(const base::FilePath& file_path) - : file_path_(file_path), - initialized_() { -} +Settings::Settings() = default; -Settings::~Settings() { -} +Settings::~Settings() = default; -bool Settings::Initialize() { +bool Settings::Initialize(const base::FilePath& file_path) { + DCHECK(initialized_.is_uninitialized()); initialized_.set_invalid(); + file_path_ = file_path; Data settings; if (!OpenForWritingAndReadSettings(&settings).is_valid()) @@ -144,18 +189,33 @@ // static Settings::ScopedLockedFileHandle Settings::MakeScopedLockedFileHandle( FileHandle file, - FileLocking locking) { + FileLocking locking, + const base::FilePath& file_path) { ScopedFileHandle scoped(file); +#if defined(OS_FUCHSIA) + base::FilePath lockfile_path(file_path.value() + ".__lock__"); + if (scoped.is_valid()) { + ScopedFileHandle lockfile_scoped( + LoggingOpenFileForWrite(lockfile_path, + FileWriteMode::kCreateOrFail, + FilePermissions::kWorldReadable)); + // This is a lightweight attempt to try to catch racy behavior. + DCHECK(lockfile_scoped.is_valid()); + return ScopedLockedFileHandle(scoped.release(), lockfile_path); + } + return ScopedLockedFileHandle(scoped.release(), base::FilePath()); +#else if (scoped.is_valid()) { if (!LoggingLockFile(scoped.get(), locking)) scoped.reset(); } return ScopedLockedFileHandle(scoped.release()); +#endif } Settings::ScopedLockedFileHandle Settings::OpenForReading() { - return MakeScopedLockedFileHandle(LoggingOpenFileForRead(file_path()), - FileLocking::kShared); + return MakeScopedLockedFileHandle( + LoggingOpenFileForRead(file_path()), FileLocking::kShared, file_path()); } Settings::ScopedLockedFileHandle Settings::OpenForReadingAndWriting( @@ -171,7 +231,8 @@ file_path(), mode, FilePermissions::kWorldReadable); } - return MakeScopedLockedFileHandle(handle, FileLocking::kExclusive); + return MakeScopedLockedFileHandle( + handle, FileLocking::kExclusive, file_path()); } bool Settings::OpenAndReadSettings(Data* out_data) {
diff --git a/third_party/crashpad/crashpad/client/settings.h b/third_party/crashpad/crashpad/client/settings.h index b64f74fb..a2b0c74 100644 --- a/third_party/crashpad/crashpad/client/settings.h +++ b/third_party/crashpad/crashpad/client/settings.h
@@ -22,6 +22,7 @@ #include "base/files/file_path.h" #include "base/macros.h" #include "base/scoped_generic.h" +#include "build/build_config.h" #include "util/file/file_io.h" #include "util/misc/initialization_state.h" #include "util/misc/uuid.h" @@ -44,10 +45,18 @@ //! should be retrieved via CrashReportDatabase::GetSettings(). class Settings { public: - explicit Settings(const base::FilePath& file_path); + Settings(); ~Settings(); - bool Initialize(); + //! \brief Initializes the settings data store. + //! + //! This method must be called only once, and must be successfully called + //! before any other method in this class may be called. + //! + //! \param[in] path The location to store the settings data. + //! \return `true` if the data store was initialized successfully, otherwise + //! `false` with an error logged. + bool Initialize(const base::FilePath& path); //! \brief Retrieves the immutable identifier for this client, which is used //! on a server to locate all crash reports from a specific Crashpad @@ -106,11 +115,45 @@ struct Data; // This must be constructed with MakeScopedLockedFileHandle(). It both unlocks - // and closes the file on destruction. + // and closes the file on destruction. Note that on Fuchsia, this handle DOES + // NOT offer correct operation, only an attempt to DCHECK if racy behavior is + // detected. +#if defined(OS_FUCHSIA) + struct ScopedLockedFileHandle { + public: + ScopedLockedFileHandle(); + ScopedLockedFileHandle(FileHandle handle, + const base::FilePath& lockfile_path); + ScopedLockedFileHandle(ScopedLockedFileHandle&& other); + ScopedLockedFileHandle& operator=(ScopedLockedFileHandle&& other); + ~ScopedLockedFileHandle(); + + // These mirror the non-Fuchsia ScopedLockedFileHandle via ScopedGeneric so + // that calling code can pretend this implementation is the same. + bool is_valid() const { return handle_ != kInvalidFileHandle; } + FileHandle get() { return handle_; } + void reset() { + Destroy(); + handle_ = kInvalidFileHandle; + lockfile_path_ = base::FilePath(); + } + + private: + void Destroy(); + + FileHandle handle_; + base::FilePath lockfile_path_; + + DISALLOW_COPY_AND_ASSIGN(ScopedLockedFileHandle); + }; +#else // OS_FUCHSIA using ScopedLockedFileHandle = base::ScopedGeneric<FileHandle, internal::ScopedLockedFileHandleTraits>; - static ScopedLockedFileHandle MakeScopedLockedFileHandle(FileHandle file, - FileLocking locking); +#endif // OS_FUCHSIA + static ScopedLockedFileHandle MakeScopedLockedFileHandle( + FileHandle file, + FileLocking locking, + const base::FilePath& file_path); // Opens the settings file for reading. On error, logs a message and returns // the invalid handle.
diff --git a/third_party/crashpad/crashpad/client/settings_test.cc b/third_party/crashpad/crashpad/client/settings_test.cc index ca961a23..3a5730b 100644 --- a/third_party/crashpad/crashpad/client/settings_test.cc +++ b/third_party/crashpad/crashpad/client/settings_test.cc
@@ -26,7 +26,7 @@ class SettingsTest : public testing::Test { public: - SettingsTest() : settings_(settings_path()) {} + SettingsTest() = default; base::FilePath settings_path() { return temp_dir_.path().Append(FILE_PATH_LITERAL("settings")); @@ -49,7 +49,7 @@ protected: // testing::Test: void SetUp() override { - ASSERT_TRUE(settings()->Initialize()); + ASSERT_TRUE(settings()->Initialize(settings_path())); } private: @@ -64,8 +64,8 @@ EXPECT_TRUE(settings()->GetClientID(&client_id)); EXPECT_NE(client_id, UUID()); - Settings local_settings(settings_path()); - EXPECT_TRUE(local_settings.Initialize()); + Settings local_settings; + EXPECT_TRUE(local_settings.Initialize(settings_path())); UUID actual; EXPECT_TRUE(local_settings.GetClientID(&actual)); EXPECT_EQ(actual, client_id); @@ -81,8 +81,8 @@ EXPECT_TRUE(settings()->GetUploadsEnabled(&enabled)); EXPECT_TRUE(enabled); - Settings local_settings(settings_path()); - EXPECT_TRUE(local_settings.Initialize()); + Settings local_settings; + EXPECT_TRUE(local_settings.Initialize(settings_path())); enabled = false; EXPECT_TRUE(local_settings.GetUploadsEnabled(&enabled)); EXPECT_TRUE(enabled); @@ -107,8 +107,8 @@ EXPECT_TRUE(settings()->GetLastUploadAttemptTime(&actual)); EXPECT_EQ(actual, expected); - Settings local_settings(settings_path()); - EXPECT_TRUE(local_settings.Initialize()); + Settings local_settings; + EXPECT_TRUE(local_settings.Initialize(settings_path())); actual = -1; EXPECT_TRUE(local_settings.GetLastUploadAttemptTime(&actual)); EXPECT_EQ(actual, expected); @@ -120,8 +120,8 @@ TEST_F(SettingsTest, BadFileOnInitialize) { InitializeBadFile(); - Settings settings(settings_path()); - EXPECT_TRUE(settings.Initialize()); + Settings settings; + EXPECT_TRUE(settings.Initialize(settings_path())); } TEST_F(SettingsTest, BadFileOnGet) { @@ -131,8 +131,8 @@ EXPECT_TRUE(settings()->GetClientID(&client_id)); EXPECT_NE(client_id, UUID()); - Settings local_settings(settings_path()); - EXPECT_TRUE(local_settings.Initialize()); + Settings local_settings; + EXPECT_TRUE(local_settings.Initialize(settings_path())); UUID actual; EXPECT_TRUE(local_settings.GetClientID(&actual)); EXPECT_EQ(actual, client_id); @@ -161,8 +161,8 @@ << ErrnoMessage("unlink"); #endif - Settings local_settings(settings_path()); - EXPECT_TRUE(local_settings.Initialize()); + Settings local_settings; + EXPECT_TRUE(local_settings.Initialize(settings_path())); UUID new_client_id; EXPECT_TRUE(local_settings.GetClientID(&new_client_id)); EXPECT_NE(new_client_id, client_id);
diff --git a/third_party/crashpad/crashpad/client/simple_string_dictionary_test.cc b/third_party/crashpad/crashpad/client/simple_string_dictionary_test.cc index 6f85e85..5fdeb5b 100644 --- a/third_party/crashpad/crashpad/client/simple_string_dictionary_test.cc +++ b/third_party/crashpad/crashpad/client/simple_string_dictionary_test.cc
@@ -253,21 +253,30 @@ #if DCHECK_IS_ON() -TEST(SimpleStringDictionaryDeathTest, NullKey) { +TEST(SimpleStringDictionaryDeathTest, SetKeyValueWithNullKey) { TSimpleStringDictionary<4, 6, 6> map; ASSERT_DEATH_CHECK(map.SetKeyValue(nullptr, "hello"), "key"); +} +TEST(SimpleStringDictionaryDeathTest, GetValueForKeyWithNullKey) { + TSimpleStringDictionary<4, 6, 6> map; map.SetKeyValue("hi", "there"); ASSERT_DEATH_CHECK(map.GetValueForKey(nullptr), "key"); EXPECT_STREQ("there", map.GetValueForKey("hi")); - - ASSERT_DEATH_CHECK(map.GetValueForKey(nullptr), "key"); - map.RemoveKey("hi"); - EXPECT_EQ(map.GetCount(), 0u); } #endif +// The tests above, without DEATH_CHECK assertions. +TEST(SimpleStringDictionaryDeathTest, GetValueForKeyWithoutNullKey) { + TSimpleStringDictionary<4, 6, 6> map; + + map.SetKeyValue("hi", "there"); + EXPECT_STREQ("there", map.GetValueForKey("hi")); + map.RemoveKey("hi"); + EXPECT_EQ(map.GetCount(), 0u); +} + } // namespace } // namespace test } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/client/simulate_crash.h b/third_party/crashpad/crashpad/client/simulate_crash.h index 299fe97..63e09a1 100644 --- a/third_party/crashpad/crashpad/client/simulate_crash.h +++ b/third_party/crashpad/crashpad/client/simulate_crash.h
@@ -21,6 +21,8 @@ #include "client/simulate_crash_mac.h" #elif defined(OS_WIN) #include "client/simulate_crash_win.h" +#elif defined(OS_LINUX) || defined(OS_ANDROID) +#include "client/simulate_crash_linux.h" #endif #endif // CRASHPAD_CLIENT_SIMULATE_CRASH_H_
diff --git a/third_party/crashpad/crashpad/client/simulate_crash_linux.h b/third_party/crashpad/crashpad/client/simulate_crash_linux.h new file mode 100644 index 0000000..e6c3e487 --- /dev/null +++ b/third_party/crashpad/crashpad/client/simulate_crash_linux.h
@@ -0,0 +1,31 @@ +// Copyright 2018 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_CLIENT_SIMULATE_CRASH_LINUX_H_ +#define CRASHPAD_CLIENT_SIMULATE_CRASH_LINUX_H_ + +#include "client/crashpad_client.h" +#include "util/misc/capture_context.h" + +//! \file + +//! \brief Captures the CPU context and simulates an exception without crashing. +#define CRASHPAD_SIMULATE_CRASH() \ + do { \ + crashpad::NativeCPUContext simulate_crash_cpu_context; \ + crashpad::CaptureContext(&simulate_crash_cpu_context); \ + crashpad::CrashpadClient::DumpWithoutCrash(&simulate_crash_cpu_context); \ + } while (false) + +#endif // CRASHPAD_CLIENT_SIMULATE_CRASH_LINUX_H_
diff --git a/third_party/crashpad/crashpad/client/simulate_crash_mac.h b/third_party/crashpad/crashpad/client/simulate_crash_mac.h index e14db3c..dcbcaae 100644 --- a/third_party/crashpad/crashpad/client/simulate_crash_mac.h +++ b/third_party/crashpad/crashpad/client/simulate_crash_mac.h
@@ -17,7 +17,7 @@ #include <mach/mach.h> -#include "client/capture_context_mac.h" +#include "util/misc/capture_context.h" //! \file
diff --git a/third_party/crashpad/crashpad/client/simulate_crash_win.h b/third_party/crashpad/crashpad/client/simulate_crash_win.h index a20f3da..140424f 100644 --- a/third_party/crashpad/crashpad/client/simulate_crash_win.h +++ b/third_party/crashpad/crashpad/client/simulate_crash_win.h
@@ -18,16 +18,17 @@ #include <windows.h> #include "client/crashpad_client.h" -#include "util/win/capture_context.h" +#include "util/misc/capture_context.h" //! \file //! \brief Captures the CPU context and captures a dump without an exception. -#define CRASHPAD_SIMULATE_CRASH() \ - do { \ - CONTEXT context; \ - crashpad::CaptureContext(&context); \ - crashpad::CrashpadClient::DumpWithoutCrash(context); \ +#define CRASHPAD_SIMULATE_CRASH() \ + do { \ + /* Not "context" to avoid variable shadowing warnings. */ \ + CONTEXT simulate_crash_cpu_context; \ + crashpad::CaptureContext(&simulate_crash_cpu_context); \ + crashpad::CrashpadClient::DumpWithoutCrash(simulate_crash_cpu_context); \ } while (false) #endif // CRASHPAD_CLIENT_SIMULATE_CRASH_WIN_H_
diff --git a/third_party/crashpad/crashpad/handler/BUILD.gn b/third_party/crashpad/crashpad/handler/BUILD.gn index 9c337697..b3370fc 100644 --- a/third_party/crashpad/crashpad/handler/BUILD.gn +++ b/third_party/crashpad/crashpad/handler/BUILD.gn
@@ -18,6 +18,8 @@ sources = [ "crash_report_upload_thread.cc", "crash_report_upload_thread.h", + "handler_main.cc", + "handler_main.h", "minidump_to_upload_parameters.cc", "minidump_to_upload_parameters.h", "prune_crash_reports_thread.cc", @@ -39,14 +41,11 @@ if (crashpad_is_linux || crashpad_is_android) { sources += [ + "linux/crash_report_exception_handler.cc", + "linux/crash_report_exception_handler.h", "linux/exception_handler_server.cc", "linux/exception_handler_server.h", ] - } else { - sources += [ - "handler_main.cc", - "handler_main.h", - ] } if (crashpad_is_win) { @@ -147,8 +146,15 @@ } if (crashpad_is_win) { - configs -= [ "//build/config/win:console" ] - configs += [ "//build/config/win:windowed" ] + if (crashpad_is_in_chromium) { + configs -= [ "//build/config/win:console" ] + configs += [ "//build/config/win:windowed" ] + } else { + configs -= + [ "//third_party/mini_chromium/mini_chromium/build:win_console" ] + configs += + [ "//third_party/mini_chromium/mini_chromium/build:win_windowed" ] + } } } @@ -199,4 +205,108 @@ "$root_out_dir/crashpad_handler.com", ] } + + executable("crash_other_program") { + testonly = true + + sources = [ + "win/crash_other_program.cc", + ] + + deps = [ + "../client", + "../test", + "../third_party/gtest:gtest", + "../third_party/mini_chromium:base", + ] + } + + executable("crashy_program") { + testonly = true + + sources = [ + "win/crashy_test_program.cc", + ] + + deps = [ + "../client", + "../third_party/mini_chromium:base", + ] + } + + executable("crashy_signal") { + testonly = true + + sources = [ + "win/crashy_signal.cc", + ] + + cflags = [ "/wd4702" ] # Unreachable code. + + deps = [ + "../client", + "../third_party/mini_chromium:base", + ] + } + + executable("fake_handler_that_crashes_at_startup") { + testonly = true + + sources = [ + "win/fake_handler_that_crashes_at_startup.cc", + ] + } + + executable("hanging_program") { + testonly = true + + sources = [ + "win/hanging_program.cc", + ] + + deps = [ + "../client", + "../third_party/mini_chromium:base", + ] + } + + loadable_module("loader_lock_dll") { + testonly = true + + sources = [ + "win/loader_lock_dll.cc", + ] + } + + executable("self_destroying_program") { + testonly = true + + sources = [ + "win/self_destroying_test_program.cc", + ] + + deps = [ + "../client", + "../compat", + "../snapshot", + "../third_party/mini_chromium:base", + ] + } + + if (current_cpu == "x86") { + # Cannot create an x64 DLL with embedded debug info. + executable("crashy_z7_loader") { + testonly = true + + sources = [ + "win/crashy_test_z7_loader.cc", + ] + + deps = [ + "../client", + "../test", + "../third_party/mini_chromium:base", + ] + } + } }
diff --git a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc index 7505524..715c533 100644 --- a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc +++ b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.cc
@@ -45,44 +45,6 @@ namespace crashpad { -namespace { - -// Calls CrashReportDatabase::RecordUploadAttempt() with |successful| set to -// false upon destruction unless disarmed by calling Fire() or Disarm(). Fire() -// triggers an immediate call. Armed upon construction. -class CallRecordUploadAttempt { - public: - CallRecordUploadAttempt(CrashReportDatabase* database, - const CrashReportDatabase::Report* report) - : database_(database), - report_(report) { - } - - ~CallRecordUploadAttempt() { - Fire(); - } - - void Fire() { - if (report_) { - database_->RecordUploadAttempt(report_, false, std::string()); - } - - Disarm(); - } - - void Disarm() { - report_ = nullptr; - } - - private: - CrashReportDatabase* database_; // weak - const CrashReportDatabase::Report* report_; // weak - - DISALLOW_COPY_AND_ASSIGN(CallRecordUploadAttempt); -}; - -} // namespace - CrashReportUploadThread::CrashReportUploadThread(CrashReportDatabase* database, const std::string& url, const Options& options) @@ -96,11 +58,18 @@ : WorkerThread::kIndefiniteWait, this), known_pending_report_uuids_(), - database_(database) {} + database_(database) { + DCHECK(!url_.empty()); +} CrashReportUploadThread::~CrashReportUploadThread() { } +void CrashReportUploadThread::ReportPending(const UUID& report_uuid) { + known_pending_report_uuids_.PushBack(report_uuid); + thread_.DoWorkNow(); +} + void CrashReportUploadThread::Start() { thread_.Start( options_.watch_pending_reports ? 0.0 : WorkerThread::kIndefiniteWait); @@ -110,11 +79,6 @@ thread_.Stop(); } -void CrashReportUploadThread::ReportPending(const UUID& report_uuid) { - known_pending_report_uuids_.PushBack(report_uuid); - thread_.DoWorkNow(); -} - void CrashReportUploadThread::ProcessPendingReports() { std::vector<UUID> known_report_uuids = known_pending_report_uuids_.Drain(); for (const UUID& report_uuid : known_report_uuids) { @@ -178,9 +142,8 @@ Settings* const settings = database_->GetSettings(); bool uploads_enabled; - if (url_.empty() || - (!report.upload_explicitly_requested && - (!settings->GetUploadsEnabled(&uploads_enabled) || !uploads_enabled))) { + if (!report.upload_explicitly_requested && + (!settings->GetUploadsEnabled(&uploads_enabled) || !uploads_enabled)) { // Don’t attempt an upload if there’s no URL to upload to. Allow upload if // it has been explicitly requested by the user, otherwise, respect the // upload-enabled state stored in the database’s settings. @@ -229,7 +192,7 @@ } } - const CrashReportDatabase::Report* upload_report; + std::unique_ptr<const CrashReportDatabase::UploadReport> upload_report; CrashReportDatabase::OperationStatus status = database_->GetReportForUploading(report.uuid, &upload_report); switch (status) { @@ -256,18 +219,16 @@ return; } - CallRecordUploadAttempt call_record_upload_attempt(database_, upload_report); - std::string response_body; - UploadResult upload_result = UploadReport(upload_report, &response_body); + UploadResult upload_result = + UploadReport(upload_report.get(), &response_body); switch (upload_result) { case UploadResult::kSuccess: - call_record_upload_attempt.Disarm(); - database_->RecordUploadAttempt(upload_report, true, response_body); + database_->RecordUploadComplete(std::move(upload_report), response_body); break; case UploadResult::kPermanentFailure: case UploadResult::kRetry: - call_record_upload_attempt.Fire(); + upload_report.reset(); // TODO(mark): Deal with retries properly: don’t call SkipReportUplaod() // if the result was kRetry and the report hasn’t already been retried @@ -279,17 +240,18 @@ } CrashReportUploadThread::UploadResult CrashReportUploadThread::UploadReport( - const CrashReportDatabase::Report* report, + const CrashReportDatabase::UploadReport* report, std::string* response_body) { +#if defined(OS_ANDROID) + // TODO(jperaza): This method can be enabled on Android after HTTPTransport is + // implemented and Crashpad takes over upload responsibilty on Android. + NOTREACHED(); + return UploadResult::kPermanentFailure; +#else std::map<std::string, std::string> parameters; - FileReader minidump_file_reader; - if (!minidump_file_reader.Open(report->file_path)) { - // If the minidump file can’t be opened, all hope is lost. - return UploadResult::kPermanentFailure; - } - - FileOffset start_offset = minidump_file_reader.SeekGet(); + FileReader* reader = report->Reader(); + FileOffset start_offset = reader->SeekGet(); if (start_offset < 0) { return UploadResult::kPermanentFailure; } @@ -299,12 +261,12 @@ // parameters, but as long as there’s a dump file, the server can decide what // to do with it. ProcessSnapshotMinidump minidump_process_snapshot; - if (minidump_process_snapshot.Initialize(&minidump_file_reader)) { + if (minidump_process_snapshot.Initialize(reader)) { parameters = BreakpadHTTPFormParametersFromMinidump(&minidump_process_snapshot); } - if (!minidump_file_reader.SeekSet(start_offset)) { + if (!reader->SeekSet(start_offset)) { return UploadResult::kPermanentFailure; } @@ -322,15 +284,10 @@ } } - http_multipart_builder.SetFileAttachment( - kMinidumpKey, -#if defined(OS_WIN) - base::UTF16ToUTF8(report->file_path.BaseName().value()), -#else - report->file_path.BaseName().value(), -#endif - &minidump_file_reader, - "application/octet-stream"); + http_multipart_builder.SetFileAttachment(kMinidumpKey, + report->uuid.ToString() + ".dmp", + reader, + "application/octet-stream"); std::unique_ptr<HTTPTransport> http_transport(HTTPTransport::Create()); HTTPHeaders content_headers; @@ -372,6 +329,7 @@ } return UploadResult::kSuccess; +#endif // OS_ANDROID } void CrashReportUploadThread::DoWork(const WorkerThread* thread) {
diff --git a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.h b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.h index cdd1502..2ec1147d 100644 --- a/third_party/crashpad/crashpad/handler/crash_report_upload_thread.h +++ b/third_party/crashpad/crashpad/handler/crash_report_upload_thread.h
@@ -22,6 +22,7 @@ #include "client/crash_report_database.h" #include "util/misc/uuid.h" #include "util/stdlib/thread_safe_vector.h" +#include "util/thread/stoppable.h" #include "util/thread/worker_thread.h" namespace crashpad { @@ -39,7 +40,8 @@ //! It also catches reports that are added without a ReportPending() signal //! being caught. This may happen if crash reports are added to the database by //! other processes. -class CrashReportUploadThread : public WorkerThread::Delegate { +class CrashReportUploadThread : public WorkerThread::Delegate, + public Stoppable { public: //! \brief Options to be passed to the CrashReportUploadThread constructor. struct Options { @@ -70,11 +72,22 @@ const Options& options); ~CrashReportUploadThread(); + //! \brief Informs the upload thread that a new pending report has been added + //! to the database. + //! + //! \param[in] report_uuid The unique identifier of the newly added pending + //! report. + //! + //! This method may be called from any thread. + void ReportPending(const UUID& report_uuid); + + // Stoppable: + //! \brief Starts a dedicated upload thread, which executes ThreadMain(). //! //! This method may only be be called on a newly-constructed object or after //! a call to Stop(). - void Start(); + void Start() override; //! \brief Stops the upload thread. //! @@ -88,16 +101,7 @@ //! //! This method may be called from any thread other than the upload thread. //! It is expected to only be called from the same thread that called Start(). - void Stop(); - - //! \brief Informs the upload thread that a new pending report has been added - //! to the database. - //! - //! \param[in] report_uuid The unique identifier of the newly added pending - //! report. - //! - //! This method may be called from any thread. - void ReportPending(const UUID& report_uuid); + void Stop() override; private: //! \brief The result code from UploadReport(). @@ -148,14 +152,14 @@ //! \param[in] report The report to upload. The caller is responsible for //! calling CrashReportDatabase::GetReportForUploading() before calling //! this method, and for calling - //! CrashReportDatabase::RecordUploadAttempt() after calling this method. + //! CrashReportDatabase::RecordUploadComplete() after calling this method. //! \param[out] response_body If the upload attempt is successful, this will //! be set to the response body sent by the server. Breakpad-type servers //! provide the crash ID assigned by the server in the response body. //! //! \return A member of UploadResult indicating the result of the upload //! attempt. - UploadResult UploadReport(const CrashReportDatabase::Report* report, + UploadResult UploadReport(const CrashReportDatabase::UploadReport* report, std::string* response_body); // WorkerThread::Delegate:
diff --git a/third_party/crashpad/crashpad/handler/crashpad_handler.md b/third_party/crashpad/crashpad/handler/crashpad_handler.md index 5eff39a..003ee2e 100644 --- a/third_party/crashpad/crashpad/handler/crashpad_handler.md +++ b/third_party/crashpad/crashpad/handler/crashpad_handler.md
@@ -73,6 +73,13 @@ stdio will be hooked up as expected to the parent console so that logging output will be visible. +On Linux/Android, the handler may create a crash dump for its parent process +using **--trace-parent-with-exception**. In this mode, the handler process +creates a crash dump for its parent and exits. Alternatively, the handler may +be launched with **--initial-client-fd** which will start the server connected +to an initial client. The server will exit when all connected client sockets are +closed. + It is not normally appropriate to invoke this program directly. Usually, it will be invoked by a Crashpad client using the Crashpad client library, or started by another system service. On macOS, arbitrary programs may be run with a Crashpad @@ -238,6 +245,18 @@ parent process. This option is only valid on macOS. Use of this option is discouraged. It should not be used absent extraordinary circumstances. + * **--trace-parent-with-exception**=_EXCEPTION-INFORMATION-ADDRESS_ + + Causes the handler process to trace its parent process and exit. The parent + process should have an ExceptionInformation struct at + _EXCEPTION-INFORMATION-ADDRESS_. + + * **--initial-client-fd**=_FD_ + + Starts the excetion handler server with an initial ExceptionHandlerClient + connected on the socket _FD_. The server will exit when all connected client + sockets have been closed. + * **--url**=_URL_ If uploads are enabled, sends crash reports to the Breakpad-type crash report
diff --git a/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc b/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc index 65fed90f..79076b8 100644 --- a/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc +++ b/third_party/crashpad/crashpad/handler/crashpad_handler_test.cc
@@ -28,7 +28,7 @@ #include "test/test_paths.h" #include "test/win/win_multiprocess_with_temp_dir.h" #include "util/file/file_reader.h" -#include "util/win/capture_context.h" +#include "util/misc/capture_context.h" namespace crashpad { namespace test {
diff --git a/third_party/crashpad/crashpad/handler/handler.gyp b/third_party/crashpad/crashpad/handler/handler.gyp index 8263dfd..60a6f251 100644 --- a/third_party/crashpad/crashpad/handler/handler.gyp +++ b/third_party/crashpad/crashpad/handler/handler.gyp
@@ -39,6 +39,8 @@ 'crash_report_upload_thread.h', 'handler_main.cc', 'handler_main.h', + 'linux/crash_report_exception_handler.cc', + 'linux/crash_report_exception_handler.h', 'linux/exception_handler_server.cc', 'linux/exception_handler_server.h', 'mac/crash_report_exception_handler.cc', @@ -56,13 +58,6 @@ 'win/crash_report_exception_handler.cc', 'win/crash_report_exception_handler.h', ], - 'conditions': [ - ['OS=="linux" or OS=="android"', { - 'sources!': [ - 'handler_main.cc', - ], - }], - ], 'target_conditions': [ ['OS=="android"', { 'sources/': [
diff --git a/third_party/crashpad/crashpad/handler/handler_main.cc b/third_party/crashpad/crashpad/handler/handler_main.cc index f175fddf..dd7adf6 100644 --- a/third_party/crashpad/crashpad/handler/handler_main.cc +++ b/third_party/crashpad/crashpad/handler/handler_main.cc
@@ -34,6 +34,7 @@ #include "base/logging.h" #include "base/metrics/persistent_histogram_allocator.h" #include "base/scoped_generic.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -46,6 +47,7 @@ #include "handler/prune_crash_reports_thread.h" #include "tools/tool_support.h" #include "util/file/file_io.h" +#include "util/misc/address_types.h" #include "util/misc/metrics.h" #include "util/misc/paths.h" #include "util/numeric/in_range_cast.h" @@ -54,7 +56,13 @@ #include "util/string/split_string.h" #include "util/synchronization/semaphore.h" -#if defined(OS_MACOSX) +#if defined(OS_LINUX) || defined(OS_ANDROID) +#include <unistd.h> + +#include "handler/linux/crash_report_exception_handler.h" +#include "handler/linux/exception_handler_server.h" +#include "util/posix/signals.h" +#elif defined(OS_MACOSX) #include <libgen.h> #include <signal.h> @@ -77,6 +85,9 @@ #elif defined(OS_FUCHSIA) #include "handler/fuchsia/crash_report_exception_handler.h" #include "handler/fuchsia/exception_handler_server.h" +#elif defined(OS_LINUX) +#include "handler/linux/crash_report_exception_handler.h" +#include "handler/linux/exception_handler_server.h" #endif // OS_MACOSX namespace crashpad { @@ -126,6 +137,11 @@ " --reset-own-crash-exception-port-to-system-default\n" " reset the server's exception handler to default\n" #endif // OS_MACOSX +#if defined(OS_LINUX) || defined(OS_ANDROID) +" --trace-parent-with-exception=EXCEPTION_INFORMATION_ADDRESS\n" +" request a dump for the handler's parent process\n" +" --initial-client-fd=FD a socket connected to a client.\n" +#endif // OS_LINUX || OS_ANDROID " --url=URL send crash reports to this Breakpad server URL,\n" " only if uploads are enabled for the database\n" " --help display this help and exit\n" @@ -145,6 +161,9 @@ std::string mach_service; int handshake_fd; bool reset_own_crash_exception_port_to_system_default; +#elif defined(OS_LINUX) || defined(OS_ANDROID) + VMAddress exception_information_address; + int initial_client_fd; #elif defined(OS_WIN) std::string pipe_name; InitialClientData initial_client_data; @@ -211,7 +230,9 @@ DISALLOW_COPY_AND_ASSIGN(CallMetricsRecordNormalExit); }; -#if defined(OS_MACOSX) +#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_ANDROID) + +Signals::OldActions g_old_crash_signal_handlers; void HandleCrashSignal(int sig, siginfo_t* siginfo, void* context) { MetricsRecordExit(Metrics::LifetimeMilestone::kCrashed); @@ -247,7 +268,9 @@ } Metrics::HandlerCrashed(metrics_code); - Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, nullptr); + struct sigaction* old_action = + g_old_crash_signal_handlers.ActionForSignal(sig); + Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, old_action); } void HandleTerminateSignal(int sig, siginfo_t* siginfo, void* context) { @@ -255,6 +278,8 @@ Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, nullptr); } +#if defined(OS_MACOSX) + void ReinstallCrashHandler() { // This is used to re-enable the metrics-recording crash handler after // MonitorSelf() sets up a Crashpad exception handler. On macOS, the @@ -293,6 +318,23 @@ g_exception_handler_server->Stop(); } +#else + +void ReinstallCrashHandler() { + // This is used to re-enable the metrics-recording crash handler after + // MonitorSelf() sets up a Crashpad signal handler. + Signals::InstallCrashHandlers( + HandleCrashSignal, 0, &g_old_crash_signal_handlers); +} + +void InstallCrashHandler() { + ReinstallCrashHandler(); + + Signals::InstallTerminateHandlers(HandleTerminateSignal, 0, nullptr); +} + +#endif // OS_MACOSX + #elif defined(OS_WIN) LONG(WINAPI* g_original_exception_filter)(EXCEPTION_POINTERS*) = nullptr; @@ -348,14 +390,18 @@ ALLOW_UNUSED_LOCAL(terminate_handler); } -#elif defined(OS_FUCHSIA) +#elif defined(OS_FUCHSIA) || defined(OS_LINUX) void InstallCrashHandler() { - NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 + // TODO(scottmg): Fuchsia: https://crashpad.chromium.org/bug/196 + // TODO(jperaza): Linux: https://crashpad.chromium.org/bug/30 + NOTREACHED(); } void ReinstallCrashHandler() { - NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 + // TODO(scottmg): Fuchsia: https://crashpad.chromium.org/bug/196 + // TODO(jperaza): Linux: https://crashpad.chromium.org/bug/30 + NOTREACHED(); } #endif // OS_MACOSX @@ -394,6 +440,16 @@ // instance of crashpad_handler to be writing metrics at a time, and it should // be the primary instance. CrashpadClient crashpad_client; +#if defined(OS_LINUX) || defined(OS_ANDROID) + if (!crashpad_client.StartHandlerAtCrash(executable_path, + options.database, + base::FilePath(), + options.url, + options.annotations, + extra_arguments)) { + return; + } +#else if (!crashpad_client.StartHandler(executable_path, options.database, base::FilePath(), @@ -404,12 +460,33 @@ false)) { return; } +#endif // Make sure that appropriate metrics will be recorded on crash before this // process is terminated. ReinstallCrashHandler(); } +class ScopedStoppable { + public: + ScopedStoppable() = default; + + ~ScopedStoppable() { + if (stoppable_) { + stoppable_->Stop(); + } + } + + void Reset(Stoppable* stoppable) { stoppable_.reset(stoppable); } + + Stoppable* Get() { return stoppable_.get(); } + + private: + std::unique_ptr<Stoppable> stoppable_; + + DISALLOW_COPY_AND_ASSIGN(ScopedStoppable); +}; + } // namespace int HandlerMain(int argc, @@ -450,6 +527,10 @@ #if defined(OS_MACOSX) kOptionResetOwnCrashExceptionPortToSystemDefault, #endif // OS_MACOSX +#if defined(OS_LINUX) || defined(OS_ANDROID) + kOptionTraceParentWithException, + kOptionInitialClientFD, +#endif kOptionURL, // Standard options. @@ -498,6 +579,13 @@ nullptr, kOptionResetOwnCrashExceptionPortToSystemDefault}, #endif // OS_MACOSX +#if defined(OS_LINUX) || defined(OS_ANDROID) + {"trace-parent-with-exception", + required_argument, + nullptr, + kOptionTraceParentWithException}, + {"initial-client-fd", required_argument, nullptr, kOptionInitialClientFD}, +#endif // OS_LINUX || OS_ANDROID {"url", required_argument, nullptr, kOptionURL}, {"help", no_argument, nullptr, kOptionHelp}, {"version", no_argument, nullptr, kOptionVersion}, @@ -512,6 +600,10 @@ options.periodic_tasks = true; options.rate_limit = true; options.upload_gzip = true; +#if defined(OS_LINUX) || defined(OS_ANDROID) + options.exception_information_address = 0; + options.initial_client_fd = kInvalidFileHandle; +#endif int opt; while ((opt = getopt_long(argc, argv, "", long_options, nullptr)) != -1) { @@ -601,6 +693,23 @@ break; } #endif // OS_MACOSX +#if defined(OS_LINUX) || defined(OS_ANDROID) + case kOptionTraceParentWithException: { + if (!StringToNumber(optarg, &options.exception_information_address)) { + ToolSupport::UsageHint( + me, "failed to parse --trace-parent-with-exception"); + return ExitFailure(); + } + break; + } + case kOptionInitialClientFD: { + if (!base::StringToInt(optarg, &options.initial_client_fd)) { + ToolSupport::UsageHint(me, "failed to parse --initial-client-fd"); + return ExitFailure(); + } + break; + } +#endif // OS_LINUX || OS_ANDROID case kOptionURL: { options.url = optarg; break; @@ -645,6 +754,14 @@ me, "--initial-client-data and --pipe-name are incompatible"); return ExitFailure(); } +#elif defined(OS_LINUX) || defined(OS_ANDROID) + if (!options.exception_information_address && + options.initial_client_fd == kInvalidFileHandle) { + ToolSupport::UsageHint( + me, + "--exception_information_address or --initial_client_fd is required"); + return ExitFailure(); + } #endif // OS_MACOSX if (options.database.empty()) { @@ -687,6 +804,50 @@ } } + std::unique_ptr<CrashReportDatabase> database( + CrashReportDatabase::Initialize(options.database)); + if (!database) { + return ExitFailure(); + } + + ScopedStoppable upload_thread; + if (!options.url.empty()) { + // TODO(scottmg): options.rate_limit should be removed when we have a + // configurable database setting to control upload limiting. + // See https://crashpad.chromium.org/bug/23. + CrashReportUploadThread::Options upload_thread_options; + upload_thread_options.identify_client_via_url = + options.identify_client_via_url; + upload_thread_options.rate_limit = options.rate_limit; + upload_thread_options.upload_gzip = options.upload_gzip; + upload_thread_options.watch_pending_reports = options.periodic_tasks; + + upload_thread.Reset(new CrashReportUploadThread( + database.get(), options.url, upload_thread_options)); + upload_thread.Get()->Start(); + } + + CrashReportExceptionHandler exception_handler( + database.get(), + static_cast<CrashReportUploadThread*>(upload_thread.Get()), + &options.annotations, + user_stream_sources); + + #if defined(OS_LINUX) || defined(OS_ANDROID) + if (options.exception_information_address) { + return exception_handler.HandleException(getppid(), + options.exception_information_address) ? + EXIT_SUCCESS : ExitFailure(); + } +#endif // OS_LINUX || OS_ANDROID + + ScopedStoppable prune_thread; + if (options.periodic_tasks) { + prune_thread.Reset(new PruneCrashReportThread( + database.get(), PruneCondition::GetDefault())); + prune_thread.Get()->Start(); + } + #if defined(OS_MACOSX) if (options.mach_service.empty()) { // Don’t do this when being run by launchd. See launchd.plist(5). @@ -740,7 +901,7 @@ if (!options.pipe_name.empty()) { exception_handler_server.SetPipeName(base::UTF8ToUTF16(options.pipe_name)); } -#elif defined(OS_FUCHSIA) +#elif defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA) ExceptionHandlerServer exception_handler_server; #endif // OS_MACOSX @@ -757,52 +918,21 @@ Metrics::HandlerLifetimeMilestone(Metrics::LifetimeMilestone::kStarted); - std::unique_ptr<CrashReportDatabase> database( - CrashReportDatabase::Initialize(options.database)); - if (!database) { - return ExitFailure(); - } - - // TODO(scottmg): options.rate_limit should be removed when we have a - // configurable database setting to control upload limiting. - // See https://crashpad.chromium.org/bug/23. - CrashReportUploadThread::Options upload_thread_options; - upload_thread_options.identify_client_via_url = - options.identify_client_via_url; - upload_thread_options.rate_limit = options.rate_limit; - upload_thread_options.upload_gzip = options.upload_gzip; - upload_thread_options.watch_pending_reports = options.periodic_tasks; - CrashReportUploadThread upload_thread(database.get(), - options.url, - upload_thread_options); - upload_thread.Start(); - - std::unique_ptr<PruneCrashReportThread> prune_thread; - if (options.periodic_tasks) { - prune_thread.reset(new PruneCrashReportThread( - database.get(), PruneCondition::GetDefault())); - prune_thread->Start(); - } - - CrashReportExceptionHandler exception_handler(database.get(), - &upload_thread, - &options.annotations, - user_stream_sources); - #if defined(OS_WIN) if (options.initial_client_data.IsValid()) { exception_handler_server.InitializeWithInheritedDataForInitialClient( options.initial_client_data, &exception_handler); } +#elif defined(OS_LINUX) || defined(OS_ANDROID) + if (options.initial_client_fd == kInvalidFileHandle || + !exception_handler_server.InitializeWithClient( + ScopedFileHandle(options.initial_client_fd))) { + return ExitFailure(); + } #endif // OS_WIN exception_handler_server.Run(&exception_handler); - upload_thread.Stop(); - if (prune_thread) { - prune_thread->Stop(); - } - return EXIT_SUCCESS; }
diff --git a/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.cc b/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.cc new file mode 100644 index 0000000..3aa46981 --- /dev/null +++ b/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.cc
@@ -0,0 +1,153 @@ +// Copyright 2018 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 "handler/linux/crash_report_exception_handler.h" + +#include <vector> + +#include "base/logging.h" +#include "client/settings.h" +#include "minidump/minidump_file_writer.h" +#include "snapshot/crashpad_info_client_options.h" +#include "snapshot/linux/process_snapshot_linux.h" +#include "util/linux/direct_ptrace_connection.h" +#include "util/linux/ptrace_client.h" +#include "util/misc/metrics.h" +#include "util/misc/tri_state.h" +#include "util/misc/uuid.h" + +namespace crashpad { + +CrashReportExceptionHandler::CrashReportExceptionHandler( + CrashReportDatabase* database, + CrashReportUploadThread* upload_thread, + const std::map<std::string, std::string>* process_annotations, + const UserStreamDataSources* user_stream_data_sources) + : database_(database), + upload_thread_(upload_thread), + process_annotations_(process_annotations), + user_stream_data_sources_(user_stream_data_sources) {} + +CrashReportExceptionHandler::~CrashReportExceptionHandler() = default; + +bool CrashReportExceptionHandler::HandleException( + pid_t client_process_id, + VMAddress exception_info_address) { + Metrics::ExceptionEncountered(); + + DirectPtraceConnection connection; + if (!connection.Initialize(client_process_id)) { + Metrics::ExceptionCaptureResult( + Metrics::CaptureResult::kDirectPtraceFailed); + return false; + } + + return HandleExceptionWithConnection(&connection, exception_info_address); +} + +bool CrashReportExceptionHandler::HandleExceptionWithBroker( + pid_t client_process_id, + VMAddress exception_info_address, + int broker_sock) { + Metrics::ExceptionEncountered(); + + PtraceClient client; + if (client.Initialize(broker_sock, client_process_id)) { + Metrics::ExceptionCaptureResult( + Metrics::CaptureResult::kBrokeredPtraceFailed); + return false; + } + + return HandleExceptionWithConnection(&client, exception_info_address); +} + +bool CrashReportExceptionHandler::HandleExceptionWithConnection( + PtraceConnection* connection, + VMAddress exception_info_address) { + ProcessSnapshotLinux process_snapshot; + if (!process_snapshot.Initialize(connection)) { + Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSnapshotFailed); + return false; + } + + if (!process_snapshot.InitializeException(exception_info_address)) { + Metrics::ExceptionCaptureResult( + Metrics::CaptureResult::kExceptionInitializationFailed); + return false; + } + + Metrics::ExceptionCode(process_snapshot.Exception()->Exception()); + + CrashpadInfoClientOptions client_options; + process_snapshot.GetCrashpadOptions(&client_options); + if (client_options.crashpad_handler_behavior != TriState::kDisabled) { + UUID client_id; + Settings* const settings = database_->GetSettings(); + if (settings) { + // If GetSettings() or GetClientID() fails, something else will log a + // message and client_id will be left at its default value, all zeroes, + // which is appropriate. + settings->GetClientID(&client_id); + } + + process_snapshot.SetClientID(client_id); + process_snapshot.SetAnnotationsSimpleMap(*process_annotations_); + + std::unique_ptr<CrashReportDatabase::NewReport> new_report; + CrashReportDatabase::OperationStatus database_status = + database_->PrepareNewCrashReport(&new_report); + if (database_status != CrashReportDatabase::kNoError) { + LOG(ERROR) << "PrepareNewCrashReport failed"; + Metrics::ExceptionCaptureResult( + Metrics::CaptureResult::kPrepareNewCrashReportFailed); + return false; + } + + process_snapshot.SetReportID(new_report->ReportID()); + + MinidumpFileWriter minidump; + minidump.InitializeFromSnapshot(&process_snapshot); + AddUserExtensionStreams( + user_stream_data_sources_, &process_snapshot, &minidump); + + if (!minidump.WriteEverything(new_report->Writer())) { + LOG(ERROR) << "WriteEverything failed"; + Metrics::ExceptionCaptureResult( + Metrics::CaptureResult::kMinidumpWriteFailed); + return false; + } + + UUID uuid; + database_status = + database_->FinishedWritingCrashReport(std::move(new_report), &uuid); + if (database_status != CrashReportDatabase::kNoError) { + LOG(ERROR) << "FinishedWritingCrashReport failed"; + Metrics::ExceptionCaptureResult( + Metrics::CaptureResult::kFinishedWritingCrashReportFailed); + return false; + } + + if (upload_thread_) { + upload_thread_->ReportPending(uuid); + } else { + database_->SkipReportUpload( + uuid, Metrics::CrashSkippedReason::kUploadsDisabled); + } + } + + Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSuccess); + return true; +} + +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.h b/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.h new file mode 100644 index 0000000..ca14f81 --- /dev/null +++ b/third_party/crashpad/crashpad/handler/linux/crash_report_exception_handler.h
@@ -0,0 +1,86 @@ +// Copyright 2018 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_HANDLER_LINUX_CRASH_REPORT_EXCEPTION_HANDLER_H_ +#define CRASHPAD_HANDLER_LINUX_CRASH_REPORT_EXCEPTION_HANDLER_H_ + +#include <map> +#include <string> + +#include "base/macros.h" +#include "client/crash_report_database.h" +#include "handler/crash_report_upload_thread.h" +#include "handler/linux/exception_handler_server.h" +#include "handler/user_stream_data_source.h" +#include "util/linux/ptrace_connection.h" +#include "util/misc/address_types.h" + +namespace crashpad { + +//! \brief An exception handler that writes crash reports for exceptions +//! to a CrashReportDatabase. +class CrashReportExceptionHandler : public ExceptionHandlerServer::Delegate { + public: + //! \brief Creates a new object that will store crash reports in \a database. + //! + //! \param[in] database The database to store crash reports in. Weak. + //! \param[in] upload_thread The upload thread to notify when a new crash + //! report is written into \a database. Report upload is skipped if this + //! value is `nullptr`. + //! \param[in] process_annotations A map of annotations to insert as + //! process-level annotations into each crash report that is written. Do + //! not confuse this with module-level annotations, which are under the + //! control of the crashing process, and are used to implement Chrome’s + //! “crash keys.” Process-level annotations are those that are beyond the + //! control of the crashing process, which must reliably be set even if + //! the process crashes before it’s able to establish its own annotations. + //! To interoperate with Breakpad servers, the recommended practice is to + //! specify values for the `"prod"` and `"ver"` keys as process + //! annotations. + //! \param[in] user_stream_data_sources Data sources to be used to extend + //! crash reports. For each crash report that is written, the data sources + //! are called in turn. These data sources may contribute additional + //! minidump streams. `nullptr` if not required. + CrashReportExceptionHandler( + CrashReportDatabase* database, + CrashReportUploadThread* upload_thread, + const std::map<std::string, std::string>* process_annotations, + const UserStreamDataSources* user_stream_data_sources); + + ~CrashReportExceptionHandler(); + + // ExceptionHandlerServer::Delegate: + + bool HandleException(pid_t client_process_id, + VMAddress exception_info_address) override; + + bool HandleExceptionWithBroker(pid_t client_process_id, + VMAddress exception_info_address, + int broker_sock) override; + + private: + bool HandleExceptionWithConnection(PtraceConnection* connection, + VMAddress exception_info_address); + + CrashReportDatabase* database_; // weak + CrashReportUploadThread* upload_thread_; // weak + const std::map<std::string, std::string>* process_annotations_; // weak + const UserStreamDataSources* user_stream_data_sources_; // weak + + DISALLOW_COPY_AND_ASSIGN(CrashReportExceptionHandler); +}; + +} // namespace crashpad + +#endif // CRASHPAD_HANDLER_LINUX_CRASH_REPORT_EXCEPTION_HANDLER_H_
diff --git a/third_party/crashpad/crashpad/handler/linux/exception_handler_server_test.cc b/third_party/crashpad/crashpad/handler/linux/exception_handler_server_test.cc index fb6c21a9..5b0c8ce 100644 --- a/third_party/crashpad/crashpad/handler/linux/exception_handler_server_test.cc +++ b/third_party/crashpad/crashpad/handler/linux/exception_handler_server_test.cc
@@ -20,11 +20,11 @@ #include "base/logging.h" #include "gtest/gtest.h" #include "test/errors.h" -#include "test/linux/scoped_pr_set_ptracer.h" #include "test/multiprocess.h" #include "util/linux/direct_ptrace_connection.h" #include "util/linux/exception_handler_client.h" #include "util/linux/ptrace_client.h" +#include "util/linux/scoped_pr_set_ptracer.h" #include "util/synchronization/semaphore.h" #include "util/thread/thread.h" @@ -205,7 +205,7 @@ // If the current ptrace_scope is restricted, the broker needs to be set // as the ptracer for this process. Setting this process as its own // ptracer allows the broker to inherit this condition. - ScopedPrSetPtracer set_ptracer(getpid()); + ScopedPrSetPtracer set_ptracer(getpid(), /* may_log= */ true); ExceptionHandlerClient client(server_test_->SockToHandler()); ASSERT_EQ(client.RequestCrashDump(info), 0);
diff --git a/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.cc b/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.cc index 6f9cdbe..edebf87 100644 --- a/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.cc +++ b/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.cc
@@ -14,6 +14,7 @@ #include "handler/mac/crash_report_exception_handler.h" +#include <utility> #include <vector> #include "base/logging.h" @@ -155,7 +156,7 @@ process_snapshot.SetClientID(client_id); process_snapshot.SetAnnotationsSimpleMap(*process_annotations_); - CrashReportDatabase::NewReport* new_report; + std::unique_ptr<CrashReportDatabase::NewReport> new_report; CrashReportDatabase::OperationStatus database_status = database_->PrepareNewCrashReport(&new_report); if (database_status != CrashReportDatabase::kNoError) { @@ -164,35 +165,34 @@ return KERN_FAILURE; } - process_snapshot.SetReportID(new_report->uuid); - - CrashReportDatabase::CallErrorWritingCrashReport - call_error_writing_crash_report(database_, new_report); - - WeakFileHandleFileWriter file_writer(new_report->handle); + process_snapshot.SetReportID(new_report->ReportID()); MinidumpFileWriter minidump; minidump.InitializeFromSnapshot(&process_snapshot); AddUserExtensionStreams( user_stream_data_sources_, &process_snapshot, &minidump); - if (!minidump.WriteEverything(&file_writer)) { + if (!minidump.WriteEverything(new_report->Writer())) { Metrics::ExceptionCaptureResult( Metrics::CaptureResult::kMinidumpWriteFailed); return KERN_FAILURE; } - call_error_writing_crash_report.Disarm(); - UUID uuid; - database_status = database_->FinishedWritingCrashReport(new_report, &uuid); + database_status = + database_->FinishedWritingCrashReport(std::move(new_report), &uuid); if (database_status != CrashReportDatabase::kNoError) { Metrics::ExceptionCaptureResult( Metrics::CaptureResult::kFinishedWritingCrashReportFailed); return KERN_FAILURE; } - upload_thread_->ReportPending(uuid); + if (upload_thread_) { + upload_thread_->ReportPending(uuid); + } else { + database_->SkipReportUpload( + uuid, Metrics::CrashSkippedReason::kUploadsDisabled); + } } if (client_options.system_crash_reporter_forwarding != TriState::kDisabled &&
diff --git a/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.h b/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.h index cc314f1..0b44de6 100644 --- a/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.h +++ b/third_party/crashpad/crashpad/handler/mac/crash_report_exception_handler.h
@@ -36,7 +36,8 @@ //! //! \param[in] database The database to store crash reports in. Weak. //! \param[in] upload_thread The upload thread to notify when a new crash - //! report is written into \a database. + //! report is written into \a database. Report upload is skipped if this + //! value is `nullptr`. //! \param[in] process_annotations A map of annotations to insert as //! process-level annotations into each crash report that is written. Do //! not confuse this with module-level annotations, which are under the
diff --git a/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.cc b/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.cc index 722275f5..7876c2fe 100644 --- a/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.cc +++ b/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.cc
@@ -38,6 +38,7 @@ } void PruneCrashReportThread::DoWork(const WorkerThread* thread) { + database_->CleanDatabase(60 * 60 * 24 * 3); PruneCrashReportDatabase(database_, condition_.get()); }
diff --git a/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.h b/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.h index 72b69fc..0fd365b0 100644 --- a/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.h +++ b/third_party/crashpad/crashpad/handler/prune_crash_reports_thread.h
@@ -18,6 +18,7 @@ #include <memory> #include "base/macros.h" +#include "util/thread/stoppable.h" #include "util/thread/worker_thread.h" namespace crashpad { @@ -31,7 +32,7 @@ //! After the thread is started, the database is pruned using the condition //! every 24 hours. Upon calling Start(), the thread waits 10 minutes before //! performing the initial prune operation. -class PruneCrashReportThread : public WorkerThread::Delegate { +class PruneCrashReportThread : public WorkerThread::Delegate, public Stoppable { public: //! \brief Constructs a new object. //! @@ -42,6 +43,8 @@ std::unique_ptr<PruneCondition> condition); ~PruneCrashReportThread(); + // Stoppable: + //! \brief Starts a dedicated pruning thread. //! //! The thread waits before running the initial prune, so as to not interfere @@ -49,7 +52,7 @@ //! //! This method may only be be called on a newly-constructed object or after //! a call to Stop(). - void Start(); + void Start() override; //! \brief Stops the pruning thread. //! @@ -58,7 +61,7 @@ //! //! This method may be called from any thread other than the pruning thread. //! It is expected to only be called from the same thread that called Start(). - void Stop(); + void Stop() override; private: // WorkerThread::Delegate:
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 55c0699..bbd25af 100644 --- a/third_party/crashpad/crashpad/handler/win/crash_other_program.cc +++ b/third_party/crashpad/crashpad/handler/win/crash_other_program.cc
@@ -122,7 +122,7 @@ DWORD exit_code = child.WaitForExit(); if (exit_code != expect_exit_code) { LOG(ERROR) << base::StringPrintf( - "incorrect exit code, expected 0x%x, observed 0x%x", + "incorrect exit code, expected 0x%lx, observed 0x%lx", expect_exit_code, exit_code); return EXIT_FAILURE;
diff --git a/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.cc b/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.cc index 0ab206c1..6d53d81 100644 --- a/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.cc +++ b/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.cc
@@ -15,6 +15,7 @@ #include "handler/win/crash_report_exception_handler.h" #include <type_traits> +#include <utility> #include "client/crash_report_database.h" #include "client/settings.h" @@ -59,7 +60,6 @@ ProcessSuspensionState::kSuspended, exception_information_address, debug_critical_section_address)) { - LOG(WARNING) << "ProcessSnapshotWin::Initialize failed"; Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSnapshotFailed); return kTerminationCodeSnapshotFailed; } @@ -90,7 +90,7 @@ process_snapshot.SetClientID(client_id); process_snapshot.SetAnnotationsSimpleMap(*process_annotations_); - CrashReportDatabase::NewReport* new_report; + std::unique_ptr<CrashReportDatabase::NewReport> new_report; CrashReportDatabase::OperationStatus database_status = database_->PrepareNewCrashReport(&new_report); if (database_status != CrashReportDatabase::kNoError) { @@ -100,29 +100,23 @@ return termination_code; } - process_snapshot.SetReportID(new_report->uuid); - - CrashReportDatabase::CallErrorWritingCrashReport - call_error_writing_crash_report(database_, new_report); - - WeakFileHandleFileWriter file_writer(new_report->handle); + process_snapshot.SetReportID(new_report->ReportID()); MinidumpFileWriter minidump; minidump.InitializeFromSnapshot(&process_snapshot); AddUserExtensionStreams( user_stream_data_sources_, &process_snapshot, &minidump); - if (!minidump.WriteEverything(&file_writer)) { + if (!minidump.WriteEverything(new_report->Writer())) { LOG(ERROR) << "WriteEverything failed"; Metrics::ExceptionCaptureResult( Metrics::CaptureResult::kMinidumpWriteFailed); return termination_code; } - call_error_writing_crash_report.Disarm(); - UUID uuid; - database_status = database_->FinishedWritingCrashReport(new_report, &uuid); + database_status = + database_->FinishedWritingCrashReport(std::move(new_report), &uuid); if (database_status != CrashReportDatabase::kNoError) { LOG(ERROR) << "FinishedWritingCrashReport failed"; Metrics::ExceptionCaptureResult( @@ -130,7 +124,12 @@ return termination_code; } - upload_thread_->ReportPending(uuid); + if (upload_thread_) { + upload_thread_->ReportPending(uuid); + } else { + database_->SkipReportUpload( + uuid, Metrics::CrashSkippedReason::kUploadsDisabled); + } } Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSuccess);
diff --git a/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.h b/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.h index e1fb725d..c2781de3 100644 --- a/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.h +++ b/third_party/crashpad/crashpad/handler/win/crash_report_exception_handler.h
@@ -37,7 +37,8 @@ //! //! \param[in] database The database to store crash reports in. Weak. //! \param[in] upload_thread The upload thread to notify when a new crash - //! report is written into \a database. + //! report is written into \a database. Report upload is skipped if this + //! value is `nullptr`. //! \param[in] process_annotations A map of annotations to insert as //! process-level annotations into each crash report that is written. Do //! not confuse this with module-level annotations, which are under the
diff --git a/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc b/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc index a5532da8..a4f4797 100644 --- a/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc +++ b/third_party/crashpad/crashpad/handler/win/crashy_test_program.cc
@@ -21,6 +21,7 @@ #include <map> #include <string> +#include <type_traits> #include <vector> #include "base/files/file_path.h" @@ -39,8 +40,8 @@ namespace crashpad { -int* g_extra_memory_pointer; -int* g_extra_memory_not_saved; +uint32_t* g_extra_memory_pointer; +uint32_t* g_extra_memory_not_saved; namespace { @@ -142,29 +143,33 @@ void AllocateExtraMemoryToBeSaved( crashpad::SimpleAddressRangeBag* extra_ranges) { - constexpr size_t kNumInts = 2000; - int* extra_memory = new int[kNumInts]; + constexpr size_t kNumVals = 2000; + auto extra_memory = new uint32_t[kNumVals]; g_extra_memory_pointer = extra_memory; - for (int i = 0; i < kNumInts; ++i) - extra_memory[i] = i * 13 + 2; - extra_ranges->Insert(extra_memory, sizeof(extra_memory[0]) * kNumInts); + for (size_t i = 0; i < kNumVals; ++i) + extra_memory[i] = + static_cast<std::remove_reference<decltype(extra_memory[0])>::type>( + i * 13 + 2); + extra_ranges->Insert(extra_memory, sizeof(extra_memory[0]) * kNumVals); extra_ranges->Insert(&g_extra_memory_pointer, sizeof(g_extra_memory_pointer)); } void AllocateExtraUnsavedMemory(crashpad::SimpleAddressRangeBag* extra_ranges) { // Allocate some extra memory, and then Insert() but also Remove() it so we // can confirm it doesn't get saved. - constexpr size_t kNumInts = 2000; - int* extra_memory = new int[kNumInts]; + constexpr size_t kNumVals = 2000; + auto extra_memory = new uint32_t[kNumVals]; g_extra_memory_not_saved = extra_memory; - for (int i = 0; i < kNumInts; ++i) - extra_memory[i] = i * 17 + 7; - extra_ranges->Insert(extra_memory, sizeof(extra_memory[0]) * kNumInts); + for (size_t i = 0; i < kNumVals; ++i) + extra_memory[i] = + static_cast<std::remove_reference<decltype(extra_memory[0])>::type>( + i * 17 + 7); + extra_ranges->Insert(extra_memory, sizeof(extra_memory[0]) * kNumVals); extra_ranges->Insert(&g_extra_memory_not_saved, sizeof(g_extra_memory_not_saved)); // We keep the pointer's memory, but remove the pointed-to memory. - extra_ranges->Remove(extra_memory, sizeof(extra_memory[0]) * kNumInts); + extra_ranges->Remove(extra_memory, sizeof(extra_memory[0]) * kNumVals); } int CrashyMain(int argc, wchar_t* argv[]) {
diff --git a/third_party/crashpad/crashpad/handler/win/loader_lock_dll.cc b/third_party/crashpad/crashpad/handler/win/loader_lock_dll.cc index cfa098b2..63c145cf 100644 --- a/third_party/crashpad/crashpad/handler/win/loader_lock_dll.cc +++ b/third_party/crashpad/crashpad/handler/win/loader_lock_dll.cc
@@ -55,7 +55,7 @@ va_end(va); if (get_last_error) { - fprintf(stderr, ": error %u", last_error); + fprintf(stderr, ": error %lu", last_error); } fputs("\n", stderr);
diff --git a/third_party/crashpad/crashpad/infra/config/cq.cfg b/third_party/crashpad/crashpad/infra/config/cq.cfg index d00ef14..64213fc3 100644 --- a/third_party/crashpad/crashpad/infra/config/cq.cfg +++ b/third_party/crashpad/crashpad/infra/config/cq.cfg
@@ -35,14 +35,18 @@ name: "master.client.crashpad" builders { name: "crashpad_try_mac_dbg" } builders { name: "crashpad_try_mac_rel" } - builders { name: "crashpad_try_win_x64_dbg" } - builders { name: "crashpad_try_win_x64_rel" } + builders { name: "crashpad_try_win_dbg" } + builders { name: "crashpad_try_win_rel" } + builders { name: "crashpad_try_linux_dbg" } + builders { name: "crashpad_try_linux_rel" } + # https://bugs.chromium.org/p/crashpad/issues/detail?id=219 QEMU runs are + # flaking; remove from CQ while being investigated. + #builders { name: "crashpad_try_fuchsia_x64_dbg" } + #builders { name: "crashpad_try_fuchsia_x64_rel" } # https://crbug.com/743139 - disabled until we can move these to swarming, # at which point we can just remove them. #builders { name: "crashpad_try_win_x86_dbg" } #builders { name: "crashpad_try_win_x86_rel" } - builders { name: "crashpad_try_win_x86_wow64_dbg" } - builders { name: "crashpad_try_win_x86_wow64_rel" } } } }
diff --git a/third_party/crashpad/crashpad/minidump/minidump_system_info_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_system_info_writer.cc index 9c665f4f..4a22b43 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_system_info_writer.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_system_info_writer.cc
@@ -123,6 +123,12 @@ case kCPUArchitectureX86_64: cpu_architecture = kMinidumpCPUArchitectureAMD64; break; + case kCPUArchitectureARM: + cpu_architecture = kMinidumpCPUArchitectureARM; + break; + case kCPUArchitectureARM64: + cpu_architecture = kMinidumpCPUArchitectureARM64; + break; default: NOTREACHED(); cpu_architecture = kMinidumpCPUArchitectureUnknown; @@ -160,6 +166,12 @@ case SystemSnapshot::kOperatingSystemWindows: operating_system = kMinidumpOSWin32NT; break; + case SystemSnapshot::kOperatingSystemLinux: + operating_system = kMinidumpOSLinux; + break; + case SystemSnapshot::kOperatingSystemAndroid: + operating_system = kMinidumpOSAndroid; + break; default: NOTREACHED(); operating_system = kMinidumpOSUnknown;
diff --git a/third_party/crashpad/crashpad/snapshot/BUILD.gn b/third_party/crashpad/crashpad/snapshot/BUILD.gn index e1d24002..5ccc735e 100644 --- a/third_party/crashpad/crashpad/snapshot/BUILD.gn +++ b/third_party/crashpad/crashpad/snapshot/BUILD.gn
@@ -34,6 +34,7 @@ "handle_snapshot.h", "memory_snapshot.cc", "memory_snapshot.h", + "memory_snapshot_generic.h", "minidump/minidump_annotation_reader.cc", "minidump/minidump_annotation_reader.h", "minidump/minidump_simple_string_dictionary_reader.cc", @@ -47,8 +48,6 @@ "minidump/process_snapshot_minidump.cc", "minidump/process_snapshot_minidump.h", "module_snapshot.h", - "posix/timezone.cc", - "posix/timezone.h", "process_snapshot.h", "snapshot_constants.h", "system_snapshot.h", @@ -57,6 +56,13 @@ "unloaded_module_snapshot.h", ] + if (crashpad_is_posix) { + sources += [ + "posix/timezone.cc", + "posix/timezone.h", + ] + } + if (crashpad_is_mac) { sources += [ "mac/cpu_context_mac.cc", @@ -71,12 +77,10 @@ "mac/mach_o_image_segment_reader.h", "mac/mach_o_image_symbol_table_reader.cc", "mac/mach_o_image_symbol_table_reader.h", - "mac/memory_snapshot_mac.cc", - "mac/memory_snapshot_mac.h", "mac/module_snapshot_mac.cc", "mac/module_snapshot_mac.h", - "mac/process_reader.cc", - "mac/process_reader.h", + "mac/process_reader_mac.cc", + "mac/process_reader_mac.h", "mac/process_snapshot_mac.cc", "mac/process_snapshot_mac.h", "mac/process_types.cc", @@ -101,20 +105,14 @@ if (crashpad_is_linux || crashpad_is_android) { sources += [ - "crashpad_types/image_annotation_reader.cc", - "crashpad_types/image_annotation_reader.h", "linux/cpu_context_linux.cc", "linux/cpu_context_linux.h", "linux/debug_rendezvous.cc", "linux/debug_rendezvous.h", "linux/exception_snapshot_linux.cc", "linux/exception_snapshot_linux.h", - "linux/memory_snapshot_linux.cc", - "linux/memory_snapshot_linux.h", - "linux/module_snapshot_linux.cc", - "linux/module_snapshot_linux.h", - "linux/process_reader.cc", - "linux/process_reader.h", + "linux/process_reader_linux.cc", + "linux/process_reader_linux.h", "linux/process_snapshot_linux.cc", "linux/process_snapshot_linux.h", "linux/signal_context.h", @@ -129,12 +127,16 @@ sources += [ "crashpad_types/crashpad_info_reader.cc", "crashpad_types/crashpad_info_reader.h", + "crashpad_types/image_annotation_reader.cc", + "crashpad_types/image_annotation_reader.h", "elf/elf_dynamic_array_reader.cc", "elf/elf_dynamic_array_reader.h", "elf/elf_image_reader.cc", "elf/elf_image_reader.h", "elf/elf_symbol_table_reader.cc", "elf/elf_symbol_table_reader.h", + "elf/module_snapshot_elf.cc", + "elf/module_snapshot_elf.h", ] } @@ -173,8 +175,12 @@ if (crashpad_is_fuchsia) { sources += [ + "fuchsia/process_reader_fuchsia.cc", + "fuchsia/process_reader_fuchsia.h", "fuchsia/process_snapshot_fuchsia.cc", "fuchsia/process_snapshot_fuchsia.h", + "fuchsia/thread_snapshot_fuchsia.cc", + "fuchsia/thread_snapshot_fuchsia.h", ] } @@ -290,7 +296,7 @@ "mac/mach_o_image_annotations_reader_test.cc", "mac/mach_o_image_reader_test.cc", "mac/mach_o_image_segment_reader_test.cc", - "mac/process_reader_test.cc", + "mac/process_reader_mac_test.cc", "mac/process_types_test.cc", "mac/system_snapshot_mac_test.cc", ] @@ -298,10 +304,9 @@ if (crashpad_is_linux || crashpad_is_android) { sources += [ - "crashpad_types/image_annotation_reader_test.cc", "linux/debug_rendezvous_test.cc", "linux/exception_snapshot_linux_test.cc", - "linux/process_reader_test.cc", + "linux/process_reader_linux_test.cc", "linux/system_snapshot_linux_test.cc", ] } else { @@ -311,6 +316,7 @@ if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) { sources += [ "crashpad_types/crashpad_info_reader_test.cc", + "crashpad_types/image_annotation_reader_test.cc", "elf/elf_image_reader_test.cc", "elf/elf_image_reader_test_note.S", "elf/test_exported_symbols.sym", @@ -329,10 +335,18 @@ "win/process_snapshot_win_test.cc", "win/system_snapshot_win_test.cc", ] - } else { + } else if (!crashpad_is_fuchsia) { + # Timezones are currently non-functional on Fuchsia: + # https://fuchsia.googlesource.com/zircon/+/master/third_party/ulib/musl/src/time/__tz.c#9 + # https://crashpad.chromium.org/bug/196. Relevant upstream bugs are ZX-337 + # and ZX-1731. sources += [ "posix/timezone_test.cc" ] } + if (crashpad_is_fuchsia) { + sources += [ "fuchsia/process_reader_fuchsia_test.cc" ] + } + # public_configs isn’t quite right. snapshot_test_link sets ldflags, and # what’s really needed is a way to push ldflags to dependent targets that # produce linker output. Luckily in this case, all dependents do produce @@ -403,10 +417,15 @@ sources = [ "crashpad_info_size_test_module.cc", ] + + deps = [] + if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) { + sources += [ "crashpad_info_size_test_note.S" ] + deps += [ "../util" ] + } + defines = [ "CRASHPAD_INFO_SIZE_TEST_MODULE_LARGE" ] - deps = [ - "../third_party/mini_chromium:base", - ] + deps += [ "../third_party/mini_chromium:base" ] } loadable_module("crashpad_snapshot_test_module_small") { @@ -414,10 +433,15 @@ sources = [ "crashpad_info_size_test_module.cc", ] + + deps = [] + if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) { + sources += [ "crashpad_info_size_test_note.S" ] + deps += [ "../util" ] + } + defines = [ "CRASHPAD_INFO_SIZE_TEST_MODULE_SMALL" ] - deps = [ - "../third_party/mini_chromium:base", - ] + deps += [ "../third_party/mini_chromium:base" ] } if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) {
diff --git a/third_party/crashpad/crashpad/snapshot/capture_memory.cc b/third_party/crashpad/crashpad/snapshot/capture_memory.cc index c860285..4327fbda9 100644 --- a/third_party/crashpad/crashpad/snapshot/capture_memory.cc +++ b/third_party/crashpad/crashpad/snapshot/capture_memory.cc
@@ -94,8 +94,20 @@ MaybeCaptureMemoryAround(delegate, context.x86->ebp); MaybeCaptureMemoryAround(delegate, context.x86->eip); } +#elif defined(ARCH_CPU_ARM_FAMILY) + if (context.architecture == kCPUArchitectureARM64) { + MaybeCaptureMemoryAround(delegate, context.arm64->pc); + for (size_t i = 0; i < arraysize(context.arm64->regs); ++i) { + MaybeCaptureMemoryAround(delegate, context.arm64->regs[i]); + } + } else { + MaybeCaptureMemoryAround(delegate, context.arm->pc); + for (size_t i = 0; i < arraysize(context.arm->regs); ++i) { + MaybeCaptureMemoryAround(delegate, context.arm->regs[i]); + } + } #else -#error non-x86 +#error Port. #endif }
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_module.cc b/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_module.cc index d39fada..53f4a3f 100644 --- a/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_module.cc +++ b/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_module.cc
@@ -23,7 +23,6 @@ #endif // OS_MACOSX namespace crashpad { -namespace { #if defined(CRASHPAD_INFO_SIZE_TEST_MODULE_SMALL) == \ defined(CRASHPAD_INFO_SIZE_TEST_MODULE_LARGE) @@ -70,16 +69,12 @@ __attribute__(( #if defined(OS_MACOSX) section(SEG_DATA ",crashpad_info"), -#elif defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA) - section("crashpad_info"), -#else -#error Port #endif #if defined(ADDRESS_SANITIZER) aligned(64), #endif // defined(ADDRESS_SANITIZER) - used, - visibility("hidden"))) + visibility("hidden"), + used)) #elif defined(OS_WIN) #pragma section("CPADinfo", read, write) __declspec(allocate("CPADinfo")) @@ -106,7 +101,6 @@ #endif // CRASHPAD_INFO_SIZE_TEST_MODULE_LARGE }; -} // namespace } // namespace crashpad extern "C" { @@ -119,6 +113,9 @@ #error Port #endif // OS_POSIX crashpad::TestCrashpadInfo* TestModule_GetCrashpadInfo() { + // Note that there's no need to do the back-reference here to the note on + // POSIX like CrashpadInfo::GetCrashpadInfo() because the note .S file is + // directly included into this test binary. return &crashpad::g_test_crashpad_info; }
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_note.S b/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_note.S new file mode 100644 index 0000000..a355a83 --- /dev/null +++ b/third_party/crashpad/crashpad/snapshot/crashpad_info_size_test_note.S
@@ -0,0 +1,56 @@ +// Copyright 2018 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. + +// This note section is used on ELF platforms to give ElfImageReader a method +// of finding the instance of CrashpadInfo g_crashpad_info without requiring +// that symbol to be in the dynamic symbol table. + +#include "build/build_config.h" +#include "util/misc/elf_note_types.h" + +// namespace crashpad { +// CrashpadInfo g_test_crashpad_info; +// } // namespace crashpad +#define TEST_CRASHPAD_INFO_SYMBOL _ZN8crashpad20g_test_crashpad_infoE + +#define NOTE_ALIGN 4 + + // This section must be "a"llocated so that it appears in the final binary at + // runtime, and "w"ritable so that the relocation to TEST_CRASHPAD_INFO_SYMBOL + // can be performed. + .section .note.crashpad.info,"aw",%note + .balign NOTE_ALIGN + .type info_size_test_note, %object +info_size_test_note: + .long name_end - name // namesz + .long desc_end - desc // descsz + .long CRASHPAD_ELF_NOTE_TYPE_CRASHPAD_INFO // type +name: + .asciz CRASHPAD_ELF_NOTE_NAME +name_end: + .balign NOTE_ALIGN +desc: +#if defined(ARCH_CPU_64_BITS) + .quad TEST_CRASHPAD_INFO_SYMBOL +#else +#if defined(ARCH_CPU_LITTLE_ENDIAN) + .long TEST_CRASHPAD_INFO_SYMBOL + .long 0 +#else + .long 0 + .long TEST_CRASHPAD_INFO_SYMBOL +#endif // ARCH_CPU_LITTLE_ENDIAN +#endif // ARCH_CPU_64_BITS +desc_end: + .size info_size_test_note, .-info_size_test_note
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader.cc b/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader.cc index ade9931..dfc438f 100644 --- a/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader.cc
@@ -81,7 +81,11 @@ return false; } - memset(reinterpret_cast<char*>(&info), 0, sizeof(info) - info.size); + if (sizeof(info) > info.size) { + memset(reinterpret_cast<char*>(&info) + info.size, + 0, + sizeof(info) - info.size); + } UnsetIfNotValidTriState(&info.crashpad_handler_behavior); UnsetIfNotValidTriState(&info.system_crash_reporter_forwarding);
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader_test.cc b/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader_test.cc index 73564177..87bafc6 100644 --- a/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader_test.cc
@@ -17,6 +17,8 @@ #include <sys/types.h> #include <unistd.h> +#include <memory> + #include "build/build_config.h" #include "client/annotation_list.h" #include "client/crashpad_info.h" @@ -43,10 +45,32 @@ constexpr uint32_t kIndirectlyReferencedMemoryCap = 42; +class ScopedUnsetCrashpadInfo { + public: + explicit ScopedUnsetCrashpadInfo(CrashpadInfo* crashpad_info) + : crashpad_info_(crashpad_info) {} + + ~ScopedUnsetCrashpadInfo() { + crashpad_info_->set_crashpad_handler_behavior(TriState::kUnset); + crashpad_info_->set_system_crash_reporter_forwarding(TriState::kUnset); + crashpad_info_->set_gather_indirectly_referenced_memory(TriState::kUnset, + 0); + crashpad_info_->set_extra_memory_ranges(nullptr); + crashpad_info_->set_simple_annotations(nullptr); + crashpad_info_->set_annotations_list(nullptr); + } + + private: + CrashpadInfo* crashpad_info_; + + DISALLOW_COPY_AND_ASSIGN(ScopedUnsetCrashpadInfo); +}; + class CrashpadInfoTestDataSetup { public: CrashpadInfoTestDataSetup() { CrashpadInfo* info = CrashpadInfo::GetCrashpadInfo(); + unset_.reset(new ScopedUnsetCrashpadInfo(info)); info->set_extra_memory_ranges(&extra_memory_); info->set_simple_annotations(&simple_annotations_); @@ -69,6 +93,7 @@ } private: + std::unique_ptr<ScopedUnsetCrashpadInfo> unset_; SimpleAddressRangeBag extra_memory_; SimpleStringDictionary simple_annotations_; AnnotationList annotation_list_;
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_types/image_annotation_reader_test.cc b/third_party/crashpad/crashpad/snapshot/crashpad_types/image_annotation_reader_test.cc index b0e635ff..63cfcfcc 100644 --- a/third_party/crashpad/crashpad/snapshot/crashpad_types/image_annotation_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/crashpad_types/image_annotation_reader_test.cc
@@ -26,11 +26,12 @@ #include "client/annotation_list.h" #include "client/simple_string_dictionary.h" #include "gtest/gtest.h" -#include "test/multiprocess.h" +#include "test/multiprocess_exec.h" +#include "test/process_type.h" #include "util/file/file_io.h" #include "util/misc/as_underlying_type.h" #include "util/misc/from_pointer_cast.h" -#include "util/process/process_memory_linux.h" +#include "util/process/process_memory_native.h" namespace crashpad { namespace test { @@ -60,67 +61,64 @@ } } -class AnnotationTest { - public: - AnnotationTest() - : expected_simple_map_(), - test_annotations_(), - expected_annotation_list_() { - expected_simple_map_.SetKeyValue("key", "value"); - expected_simple_map_.SetKeyValue("key2", "value2"); +void BuildTestStructures( + std::vector<std::unique_ptr<Annotation>>* annotations_storage, + SimpleStringDictionary* into_map, + AnnotationList* into_annotation_list) { + into_map->SetKeyValue("key", "value"); + into_map->SetKeyValue("key2", "value2"); - static constexpr char kAnnotationName[] = "test annotation"; - static constexpr char kAnnotationValue[] = "test annotation value"; - test_annotations_.push_back(std::make_unique<Annotation>( - Annotation::Type::kString, - kAnnotationName, - reinterpret_cast<void*>(const_cast<char*>(kAnnotationValue)))); - test_annotations_.back()->SetSize(sizeof(kAnnotationValue)); - expected_annotation_list_.Add(test_annotations_.back().get()); + static constexpr char kAnnotationName[] = "test annotation"; + static constexpr char kAnnotationValue[] = "test annotation value"; + annotations_storage->push_back(std::make_unique<Annotation>( + Annotation::Type::kString, + kAnnotationName, + reinterpret_cast<void*>(const_cast<char*>(kAnnotationValue)))); + annotations_storage->back()->SetSize(sizeof(kAnnotationValue)); + into_annotation_list->Add(annotations_storage->back().get()); - static constexpr char kAnnotationName2[] = "test annotation2"; - static constexpr char kAnnotationValue2[] = "test annotation value2"; - test_annotations_.push_back(std::make_unique<Annotation>( - Annotation::Type::kString, - kAnnotationName2, - reinterpret_cast<void*>(const_cast<char*>(kAnnotationValue2)))); - test_annotations_.back()->SetSize(sizeof(kAnnotationValue2)); - expected_annotation_list_.Add(test_annotations_.back().get()); - } + static constexpr char kAnnotationName2[] = "test annotation2"; + static constexpr char kAnnotationValue2[] = "test annotation value2"; + annotations_storage->push_back(std::make_unique<Annotation>( + Annotation::Type::kString, + kAnnotationName2, + reinterpret_cast<void*>(const_cast<char*>(kAnnotationValue2)))); + annotations_storage->back()->SetSize(sizeof(kAnnotationValue2)); + into_annotation_list->Add(annotations_storage->back().get()); +} - ~AnnotationTest() = default; +void ExpectAnnotations(ProcessType process, + bool is_64_bit, + VMAddress simple_map_address, + VMAddress annotation_list_address) { + ProcessMemoryNative memory; + ASSERT_TRUE(memory.Initialize(process)); - void ExpectAnnotations(pid_t pid, bool is_64_bit) { - ProcessMemoryLinux memory; - ASSERT_TRUE(memory.Initialize(pid)); + ProcessMemoryRange range; + ASSERT_TRUE(range.Initialize(&memory, is_64_bit)); - ProcessMemoryRange range; - ASSERT_TRUE(range.Initialize(&memory, is_64_bit)); + SimpleStringDictionary expected_simple_map; + std::vector<std::unique_ptr<Annotation>> storage; + AnnotationList expected_annotations; + BuildTestStructures(&storage, &expected_simple_map, &expected_annotations); - ImageAnnotationReader reader(&range); + ImageAnnotationReader reader(&range); - std::map<std::string, std::string> simple_map; - ASSERT_TRUE(reader.SimpleMap( - FromPointerCast<VMAddress>(&expected_simple_map_), &simple_map)); - ExpectSimpleMap(simple_map, expected_simple_map_); + std::map<std::string, std::string> simple_map; + ASSERT_TRUE(reader.SimpleMap(simple_map_address, &simple_map)); + ExpectSimpleMap(simple_map, expected_simple_map); - std::vector<AnnotationSnapshot> annotation_list; - ASSERT_TRUE(reader.AnnotationsList( - FromPointerCast<VMAddress>(&expected_annotation_list_), - &annotation_list)); - ExpectAnnotationList(annotation_list, expected_annotation_list_); - } - - private: - SimpleStringDictionary expected_simple_map_; - std::vector<std::unique_ptr<Annotation>> test_annotations_; - AnnotationList expected_annotation_list_; - - DISALLOW_COPY_AND_ASSIGN(AnnotationTest); -}; + std::vector<AnnotationSnapshot> annotation_list; + ASSERT_TRUE( + reader.AnnotationsList(annotation_list_address, &annotation_list)); + ExpectAnnotationList(annotation_list, expected_annotations); +} TEST(ImageAnnotationReader, ReadFromSelf) { - AnnotationTest test; + SimpleStringDictionary map; + std::vector<std::unique_ptr<Annotation>> storage; + AnnotationList annotations; + BuildTestStructures(&storage, &map, &annotations); #if defined(ARCH_CPU_64_BITS) constexpr bool am_64_bit = true; @@ -128,14 +126,35 @@ constexpr bool am_64_bit = false; #endif - test.ExpectAnnotations(getpid(), am_64_bit); + ExpectAnnotations(GetSelfProcess(), + am_64_bit, + FromPointerCast<VMAddress>(&map), + FromPointerCast<VMAddress>(&annotations)); } -class ReadFromChildTest : public Multiprocess { - public: - ReadFromChildTest() : Multiprocess(), annotation_test_() {} +CRASHPAD_CHILD_TEST_MAIN(ReadAnnotationsFromChildTestMain) { + SimpleStringDictionary map; + std::vector<std::unique_ptr<Annotation>> storage; + AnnotationList annotations; + BuildTestStructures(&storage, &map, &annotations); - ~ReadFromChildTest() {} + VMAddress simple_map_address = FromPointerCast<VMAddress>(&map); + VMAddress annotations_address = FromPointerCast<VMAddress>(&annotations); + FileHandle out = StdioFileHandle(StdioStream::kStandardOutput); + CheckedWriteFile(out, &simple_map_address, sizeof(simple_map_address)); + CheckedWriteFile(out, &annotations_address, sizeof(annotations_address)); + + CheckedReadFileAtEOF(StdioFileHandle(StdioStream::kStandardInput)); + return 0; +} + +class ReadFromChildTest : public MultiprocessExec { + public: + ReadFromChildTest() : MultiprocessExec() { + SetChildTestMainFunction("ReadAnnotationsFromChildTestMain"); + } + + ~ReadFromChildTest() = default; private: void MultiprocessParent() { @@ -144,13 +163,17 @@ #else constexpr bool am_64_bit = false; #endif - annotation_test_.ExpectAnnotations(ChildPID(), am_64_bit); + + VMAddress simple_map_address; + VMAddress annotations_address; + ASSERT_TRUE(ReadFileExactly( + ReadPipeHandle(), &simple_map_address, sizeof(simple_map_address))); + ASSERT_TRUE(ReadFileExactly( + ReadPipeHandle(), &annotations_address, sizeof(annotations_address))); + ExpectAnnotations( + ChildProcess(), am_64_bit, simple_map_address, annotations_address); } - void MultiprocessChild() { CheckedReadFileAtEOF(ReadPipeHandle()); } - - AnnotationTest annotation_test_; - DISALLOW_COPY_AND_ASSIGN(ReadFromChildTest); };
diff --git a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader.cc b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader.cc index 2fc9608..c681660 100644 --- a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader.cc
@@ -164,7 +164,7 @@ VMSize* size) const override { INITIALIZATION_STATE_DCHECK_VALID(initialized_); for (size_t index = *start_index; index < table_.size(); ++index) { - if (table_[index].p_type == PT_NOTE) { + if (table_[index].p_type == PT_NOTE && table_[index].p_vaddr != 0) { *start_index = index + 1; *address = table_[index].p_vaddr; *size = table_[index].p_memsz;
diff --git a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test.cc b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test.cc index dc13ad6f..91cce068 100644 --- a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test.cc
@@ -27,6 +27,7 @@ #include "test/test_paths.h" #include "util/file/file_io.h" #include "util/misc/address_types.h" +#include "util/misc/elf_note_types.h" #include "util/misc/from_pointer_cast.h" #include "util/process/process_memory_native.h" @@ -163,14 +164,14 @@ ElfImageReader::NoteReader::Result::kNoMoreNotes); // Find the note defined in elf_image_reader_test_note.S. - constexpr char kCrashpadNoteName[] = "Crashpad"; - constexpr ElfImageReader::NoteReader::NoteType kCrashpadNoteType = 1; constexpr uint32_t kCrashpadNoteDesc = 42; - notes = reader.NotesWithNameAndType(kCrashpadNoteName, kCrashpadNoteType, -1); + notes = reader.NotesWithNameAndType( + CRASHPAD_ELF_NOTE_NAME, CRASHPAD_ELF_NOTE_TYPE_SNAPSHOT_TEST, -1); ASSERT_EQ(notes->NextNote(¬e_name, ¬e_type, ¬e_desc), ElfImageReader::NoteReader::Result::kSuccess); - EXPECT_EQ(note_name, kCrashpadNoteName); - EXPECT_EQ(note_type, kCrashpadNoteType); + EXPECT_EQ(note_name, CRASHPAD_ELF_NOTE_NAME); + EXPECT_EQ(note_type, + implicit_cast<unsigned int>(CRASHPAD_ELF_NOTE_TYPE_SNAPSHOT_TEST)); EXPECT_EQ(note_desc.size(), sizeof(kCrashpadNoteDesc)); EXPECT_EQ(*reinterpret_cast<decltype(kCrashpadNoteDesc)*>(¬e_desc[0]), kCrashpadNoteDesc);
diff --git a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test_note.S b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test_note.S index e41a520..9ab0338 100644 --- a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test_note.S +++ b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test_note.S
@@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "util/misc/elf_note_types.h" + #define NOTE_ALIGN 4 .section .note.crashpad.test,"a",%note .balign NOTE_ALIGN @@ -19,9 +21,9 @@ testnote: .long name_end - name // namesz .long desc_end - desc // descsz - .long 1 // type + .long CRASHPAD_ELF_NOTE_TYPE_SNAPSHOT_TEST // type name: - .ascii "Crashpad\0" + .asciz CRASHPAD_ELF_NOTE_NAME name_end: .balign NOTE_ALIGN desc:
diff --git a/third_party/crashpad/crashpad/snapshot/linux/module_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/elf/module_snapshot_elf.cc similarity index 64% rename from third_party/crashpad/crashpad/snapshot/linux/module_snapshot_linux.cc rename to third_party/crashpad/crashpad/snapshot/elf/module_snapshot_elf.cc index 0ddbebf..5c5039ee1 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/module_snapshot_linux.cc +++ b/third_party/crashpad/crashpad/snapshot/elf/module_snapshot_elf.cc
@@ -12,46 +12,52 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "snapshot/linux/module_snapshot_linux.h" +#include "snapshot/elf/module_snapshot_elf.h" #include <algorithm> #include "base/files/file_path.h" #include "snapshot/crashpad_types/image_annotation_reader.h" +#include "util/misc/elf_note_types.h" namespace crashpad { namespace internal { -ModuleSnapshotLinux::ModuleSnapshotLinux() +ModuleSnapshotElf::ModuleSnapshotElf(const std::string& name, + ElfImageReader* elf_reader, + ModuleSnapshot::ModuleType type) : ModuleSnapshot(), - name_(), - elf_reader_(nullptr), + name_(name), + elf_reader_(elf_reader), crashpad_info_(), - type_(kModuleTypeUnknown), + type_(type), initialized_() {} -ModuleSnapshotLinux::~ModuleSnapshotLinux() = default; +ModuleSnapshotElf::~ModuleSnapshotElf() = default; -bool ModuleSnapshotLinux::Initialize( - const ProcessReader::Module& process_reader_module) { +bool ModuleSnapshotElf::Initialize() { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); - if (!process_reader_module.elf_reader) { + if (!elf_reader_) { LOG(ERROR) << "no elf reader"; return false; } - name_ = process_reader_module.name; - elf_reader_ = process_reader_module.elf_reader; - type_ = process_reader_module.type; - + // The data payload is only sizeof(VMAddress) in the note, but add a bit to + // account for the name, header, and padding. + constexpr ssize_t kMaxNoteSize = 256; + std::unique_ptr<ElfImageReader::NoteReader> notes = + elf_reader_->NotesWithNameAndType(CRASHPAD_ELF_NOTE_NAME, + CRASHPAD_ELF_NOTE_TYPE_CRASHPAD_INFO, + kMaxNoteSize); + std::string desc; VMAddress info_address; - VMSize info_size; - if (elf_reader_->GetDynamicSymbol( - "g_crashpad_info", &info_address, &info_size)) { + if (notes->NextNote(nullptr, nullptr, &desc) == + ElfImageReader::NoteReader::Result::kSuccess) { + info_address = *reinterpret_cast<VMAddress*>(&desc[0]); + ProcessMemoryRange range; - if (range.Initialize(*elf_reader_->Memory()) && - range.RestrictRange(info_address, info_size)) { + if (range.Initialize(*elf_reader_->Memory())) { auto info = std::make_unique<CrashpadInfoReader>(); if (info->Initialize(&range, info_address)) { crashpad_info_ = std::move(info); @@ -63,8 +69,7 @@ return true; } -bool ModuleSnapshotLinux::GetCrashpadOptions( - CrashpadInfoClientOptions* options) { +bool ModuleSnapshotElf::GetCrashpadOptions(CrashpadInfoClientOptions* options) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); if (!crashpad_info_) { @@ -82,27 +87,38 @@ return true; } -std::string ModuleSnapshotLinux::Name() const { +std::string ModuleSnapshotElf::Name() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return name_; } -uint64_t ModuleSnapshotLinux::Address() const { +uint64_t ModuleSnapshotElf::Address() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return elf_reader_->Address(); } -uint64_t ModuleSnapshotLinux::Size() const { +uint64_t ModuleSnapshotElf::Size() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return elf_reader_->Size(); } -time_t ModuleSnapshotLinux::Timestamp() const { +time_t ModuleSnapshotElf::Timestamp() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return 0; } -void ModuleSnapshotLinux::FileVersion(uint16_t* version_0, +void ModuleSnapshotElf::FileVersion(uint16_t* version_0, + uint16_t* version_1, + uint16_t* version_2, + uint16_t* version_3) const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + *version_0 = 0; + *version_1 = 0; + *version_2 = 0; + *version_3 = 0; +} + +void ModuleSnapshotElf::SourceVersion(uint16_t* version_0, uint16_t* version_1, uint16_t* version_2, uint16_t* version_3) const { @@ -113,24 +129,12 @@ *version_3 = 0; } -void ModuleSnapshotLinux::SourceVersion(uint16_t* version_0, - uint16_t* version_1, - uint16_t* version_2, - uint16_t* version_3) const { - INITIALIZATION_STATE_DCHECK_VALID(initialized_); - *version_0 = 0; - *version_1 = 0; - *version_2 = 0; - *version_3 = 0; -} - -ModuleSnapshot::ModuleType ModuleSnapshotLinux::GetModuleType() const { +ModuleSnapshot::ModuleType ModuleSnapshotElf::GetModuleType() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return type_; } -void ModuleSnapshotLinux::UUIDAndAge(crashpad::UUID* uuid, - uint32_t* age) const { +void ModuleSnapshotElf::UUIDAndAge(crashpad::UUID* uuid, uint32_t* age) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); *age = 0; @@ -142,17 +146,17 @@ uuid->InitializeFromBytes(reinterpret_cast<const uint8_t*>(&desc[0])); } -std::string ModuleSnapshotLinux::DebugFileName() const { +std::string ModuleSnapshotElf::DebugFileName() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return base::FilePath(Name()).BaseName().value(); } -std::vector<std::string> ModuleSnapshotLinux::AnnotationsVector() const { +std::vector<std::string> ModuleSnapshotElf::AnnotationsVector() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return std::vector<std::string>(); } -std::map<std::string, std::string> ModuleSnapshotLinux::AnnotationsSimpleMap() +std::map<std::string, std::string> ModuleSnapshotElf::AnnotationsSimpleMap() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::map<std::string, std::string> annotations; @@ -163,7 +167,7 @@ return annotations; } -std::vector<AnnotationSnapshot> ModuleSnapshotLinux::AnnotationObjects() const { +std::vector<AnnotationSnapshot> ModuleSnapshotElf::AnnotationObjects() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::vector<AnnotationSnapshot> annotations; if (crashpad_info_ && crashpad_info_->AnnotationsList()) { @@ -173,14 +177,13 @@ return annotations; } -std::set<CheckedRange<uint64_t>> ModuleSnapshotLinux::ExtraMemoryRanges() - const { +std::set<CheckedRange<uint64_t>> ModuleSnapshotElf::ExtraMemoryRanges() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return std::set<CheckedRange<uint64_t>>(); } std::vector<const UserMinidumpStream*> -ModuleSnapshotLinux::CustomMinidumpStreams() const { +ModuleSnapshotElf::CustomMinidumpStreams() const { return std::vector<const UserMinidumpStream*>(); }
diff --git a/third_party/crashpad/crashpad/snapshot/linux/module_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/elf/module_snapshot_elf.h similarity index 79% rename from third_party/crashpad/crashpad/snapshot/linux/module_snapshot_linux.h rename to third_party/crashpad/crashpad/snapshot/elf/module_snapshot_elf.h index b277ff7..1f7cf65 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/module_snapshot_linux.h +++ b/third_party/crashpad/crashpad/snapshot/elf/module_snapshot_elf.h
@@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef CRASHPAD_SNAPSHOT_LINUX_MODULE_SNAPSHOT_LINUX_H_ -#define CRASHPAD_SNAPSHOT_LINUX_MODULE_SNAPSHOT_LINUX_H_ +#ifndef CRASHPAD_SNAPSHOT_ELF_MODULE_SNAPSHOT_ELF_H_ +#define CRASHPAD_SNAPSHOT_ELF_MODULE_SNAPSHOT_ELF_H_ #include <stdint.h> #include <sys/types.h> @@ -27,7 +27,6 @@ #include "snapshot/crashpad_info_client_options.h" #include "snapshot/crashpad_types/crashpad_info_reader.h" #include "snapshot/elf/elf_image_reader.h" -#include "snapshot/linux/process_reader.h" #include "snapshot/module_snapshot.h" #include "util/misc/initialization_state_dcheck.h" @@ -36,20 +35,22 @@ namespace internal { //! \brief A ModuleSnapshot of a code module (binary image) loaded into a -//! running (or crashed) process on a Linux system. -class ModuleSnapshotLinux final : public ModuleSnapshot { +//! running (or crashed) process on a system that uses ELF modules. +class ModuleSnapshotElf final : public ModuleSnapshot { public: - ModuleSnapshotLinux(); - ~ModuleSnapshotLinux() override; + //! \param[in] name The pathname used to load the module from disk. + //! \param[in] elf_reader An image reader for the module. + //! \param[in] type The module's type. + ModuleSnapshotElf(const std::string& name, + ElfImageReader* elf_reader, + ModuleSnapshot::ModuleType type); + ~ModuleSnapshotElf() override; //! \brief Initializes the object. //! - //! \param[in] process_reader_module The module within the ProcessReader for - //! which the snapshot should be created. - //! //! \return `true` if the snapshot could be created, `false` otherwise with //! an appropriate message logged. - bool Initialize(const ProcessReader::Module& process_reader_module); + bool Initialize(); //! \brief Returns options from the module’s CrashpadInfo structure. //! @@ -87,10 +88,10 @@ ModuleType type_; InitializationStateDcheck initialized_; - DISALLOW_COPY_AND_ASSIGN(ModuleSnapshotLinux); + DISALLOW_COPY_AND_ASSIGN(ModuleSnapshotElf); }; } // namespace internal } // namespace crashpad -#endif // CRASHPAD_SNAPSHOT_LINUX_MODULE_SNAPSHOT_LINUX_H_ +#endif // CRASHPAD_SNAPSHOT_ELF_MODULE_SNAPSHOT_ELF_H_
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.cc new file mode 100644 index 0000000..1ace0d13 --- /dev/null +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.cc
@@ -0,0 +1,266 @@ +// Copyright 2018 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/fuchsia/process_reader_fuchsia.h" + +#include <link.h> +#include <zircon/syscalls.h> + +#include "base/fuchsia/fuchsia_logging.h" +#include "base/fuchsia/scoped_zx_handle.h" +#include "base/logging.h" + +namespace crashpad { + +ProcessReaderFuchsia::Module::Module() = default; + +ProcessReaderFuchsia::Module::~Module() = default; + +ProcessReaderFuchsia::Thread::Thread() = default; + +ProcessReaderFuchsia::Thread::~Thread() = default; + +ProcessReaderFuchsia::ProcessReaderFuchsia() = default; + +ProcessReaderFuchsia::~ProcessReaderFuchsia() = default; + +bool ProcessReaderFuchsia::Initialize(zx_handle_t process) { + INITIALIZATION_STATE_SET_INITIALIZING(initialized_); + + process_ = process; + + process_memory_.reset(new ProcessMemoryFuchsia()); + process_memory_->Initialize(process_); + + INITIALIZATION_STATE_SET_VALID(initialized_); + return true; +} + +const std::vector<ProcessReaderFuchsia::Module>& +ProcessReaderFuchsia::Modules() { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + if (!initialized_modules_) { + InitializeModules(); + } + + return modules_; +} + +const std::vector<ProcessReaderFuchsia::Thread>& +ProcessReaderFuchsia::Threads() { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + if (!initialized_threads_) { + InitializeThreads(); + } + + return threads_; +} + +void ProcessReaderFuchsia::InitializeModules() { + DCHECK(!initialized_modules_); + DCHECK(modules_.empty()); + + initialized_modules_ = true; + + // TODO(scottmg): <inspector/inspector.h> does some of this, but doesn't + // expose any of the data that's necessary to fill out a Module after it + // retrieves (some of) the data into internal structures. It may be worth + // trying to refactor/upstream some of this into Fuchsia. + + std::string app_name("app:"); + { + char name[ZX_MAX_NAME_LEN]; + zx_status_t status = + zx_object_get_property(process_, ZX_PROP_NAME, name, sizeof(name)); + if (status != ZX_OK) { + LOG(ERROR) << "zx_object_get_property ZX_PROP_NAME"; + return; + } + + app_name += name; + } + + // Starting from the ld.so's _dl_debug_addr, read the link_map structure and + // walk the list to fill out modules_. + + uintptr_t debug_address; + zx_status_t status = zx_object_get_property(process_, + ZX_PROP_PROCESS_DEBUG_ADDR, + &debug_address, + sizeof(debug_address)); + if (status != ZX_OK || debug_address == 0) { + LOG(ERROR) << "zx_object_get_property ZX_PROP_PROCESS_DEBUG_ADDR"; + return; + } + + constexpr auto k_r_debug_map_offset = offsetof(r_debug, r_map); + uintptr_t map; + if (!process_memory_->Read( + debug_address + k_r_debug_map_offset, sizeof(map), &map)) { + LOG(ERROR) << "read link_map"; + return; + } + + int i = 0; + constexpr int kMaxDso = 1000; // Stop after an unreasonably large number. + while (map != 0) { + if (++i >= kMaxDso) { + LOG(ERROR) << "possibly circular dso list, terminating"; + return; + } + + constexpr auto k_link_map_addr_offset = offsetof(link_map, l_addr); + zx_vaddr_t base; + if (!process_memory_->Read( + map + k_link_map_addr_offset, sizeof(base), &base)) { + LOG(ERROR) << "Read base"; + // Could theoretically continue here, but realistically if any part of + // link_map fails to read, things are looking bad, so just abort. + break; + } + + constexpr auto k_link_map_next_offset = offsetof(link_map, l_next); + zx_vaddr_t next; + if (!process_memory_->Read( + map + k_link_map_next_offset, sizeof(next), &next)) { + LOG(ERROR) << "Read next"; + break; + } + + constexpr auto k_link_map_name_offset = offsetof(link_map, l_name); + zx_vaddr_t name_address; + if (!process_memory_->Read(map + k_link_map_name_offset, + sizeof(name_address), + &name_address)) { + LOG(ERROR) << "Read name address"; + break; + } + + std::string dsoname; + if (!process_memory_->ReadCString(name_address, &dsoname)) { + // In this case, it could be reasonable to continue on to the next module + // as this data isn't strictly in the link_map. + LOG(ERROR) << "ReadCString name"; + } + + Module module; + if (dsoname.empty()) { + module.name = app_name; + module.type = ModuleSnapshot::kModuleTypeExecutable; + } else { + module.name = dsoname; + // TODO(scottmg): Handle kModuleTypeDynamicLoader. + module.type = ModuleSnapshot::kModuleTypeSharedLibrary; + } + + std::unique_ptr<ElfImageReader> reader(new ElfImageReader()); + + std::unique_ptr<ProcessMemoryRange> process_memory_range( + new ProcessMemoryRange()); + // TODO(scottmg): Could this be limited range? + process_memory_range->Initialize(process_memory_.get(), true); + process_memory_ranges_.push_back(std::move(process_memory_range)); + + reader->Initialize(*process_memory_ranges_.back(), base); + module.reader = reader.get(); + module_readers_.push_back(std::move(reader)); + modules_.push_back(module); + + map = next; + } +} + +void ProcessReaderFuchsia::InitializeThreads() { + DCHECK(!initialized_threads_); + DCHECK(threads_.empty()); + + initialized_threads_ = true; + + // Retrieve the thread koids. This is racy; better if the process is suspended + // itself, but threads could still be externally created. As there's no + // maximum, this needs to be retried in a loop until the actual threads + // retrieved is equal to the available threads. + + std::vector<zx_koid_t> threads(100); + size_t actual_num_threads, available_num_threads; + for (;;) { + zx_status_t status = zx_object_get_info(process_, + ZX_INFO_PROCESS_THREADS, + &threads[0], + sizeof(threads[0]) * threads.size(), + &actual_num_threads, + &available_num_threads); + // If the buffer is too small (even zero), the result is still ZX_OK, not + // ZX_ERR_BUFFER_TOO_SMALL. + if (status != ZX_OK) { + ZX_LOG(ERROR, status) << "zx_object_get_info ZX_INFO_PROCESS_THREADS"; + break; + } + if (actual_num_threads == available_num_threads) { + threads.resize(actual_num_threads); + break; + } + + // Resize to the expected number next time with a bit extra to attempt to + // handle the race between here and the next request. + threads.resize(available_num_threads + 10); + } + + for (const zx_koid_t thread_koid : threads) { + zx_handle_t raw_handle; + zx_status_t status = zx_object_get_child( + process_, thread_koid, ZX_RIGHT_SAME_RIGHTS, &raw_handle); + if (status != ZX_OK) { + ZX_LOG(ERROR, status) << "zx_object_get_child"; + // TODO(scottmg): Decide if it's worthwhile adding a mostly-empty Thread + // here, consisting only of the koid, but no other information. The only + // time this is expected to happen is when there's a race between getting + // the koid above, and requesting the handle here. + continue; + } + + base::ScopedZxHandle thread_handle(raw_handle); + + Thread thread; + thread.id = thread_koid; + + char name[ZX_MAX_NAME_LEN] = {0}; + status = zx_object_get_property( + thread_handle.get(), ZX_PROP_NAME, &name, sizeof(name)); + if (status != ZX_OK) { + ZX_LOG(WARNING, status) << "zx_object_get_property ZX_PROP_NAME"; + } else { + thread.name.assign(name); + } + + zx_info_thread_t thread_info; + status = zx_object_get_info(thread_handle.get(), + ZX_INFO_THREAD, + &thread_info, + sizeof(thread_info), + nullptr, + nullptr); + if (status != ZX_OK) { + ZX_LOG(WARNING, status) << "zx_object_get_info ZX_INFO_THREAD"; + } else { + thread.state = thread_info.state; + } + + threads_.push_back(thread); + } +} + +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.h b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.h new file mode 100644 index 0000000..d0811cfe --- /dev/null +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia.h
@@ -0,0 +1,121 @@ +// Copyright 2018 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_FUCHSIA_PROCESS_READER_H_ +#define CRASHPAD_SNAPSHOT_FUCHSIA_PROCESS_READER_H_ + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "build/build_config.h" +#include "snapshot/elf/elf_image_reader.h" +#include "snapshot/module_snapshot.h" +#include "util/misc/initialization_state_dcheck.h" +#include "util/process/process_memory_fuchsia.h" +#include "util/process/process_memory_range.h" + +namespace crashpad { + +//! \brief Accesses information about another process, identified by a Fuchsia +//! process. +class ProcessReaderFuchsia { + public: + //! \brief Contains information about a module loaded into a process. + struct Module { + Module(); + ~Module(); + + //! \brief The `ZX_PROP_NAME` of the module. Will be prepended with "app:" + //! for the main executable. + std::string name; + + //! \brief An image reader for the module. + //! + //! The lifetime of this ElfImageReader is scoped to the lifetime of the + //! ProcessReaderFuchsia that created it. + //! + //! This field may be `nullptr` if a reader could not be created for the + //! module. + ElfImageReader* reader; + + //! \brief The module's type. + ModuleSnapshot::ModuleType type = ModuleSnapshot::kModuleTypeUnknown; + }; + + //! \brief Contains information about a thread that belongs to a process. + struct Thread { + Thread(); + ~Thread(); + + //! \brief The kernel identifier for the thread. + zx_koid_t id = ZX_KOID_INVALID; + + //! \brief The state of the thread, the `ZX_THREAD_STATE_*` value or `-1` if + //! the value could not be retrieved. + uint32_t state = -1; + + //! \brief The `ZX_PROP_NAME` property of the thread. This may be empty. + std::string name; + }; + + ProcessReaderFuchsia(); + ~ProcessReaderFuchsia(); + + //! \brief Initializes this object. This method must be called before any + //! other. + //! + //! \param[in] process A process handle with permissions to read properties + //! and memory from the target process. + //! + //! \return `true` on success, indicating that this object will respond + //! validly to further method calls. `false` on failure. On failure, no + //! further method calls should be made. + bool Initialize(zx_handle_t process); + + //! \return The modules loaded in the process. The first element (at index + //! `0`) corresponds to the main executable. + const std::vector<Module>& Modules(); + + //! \return The threads that are in the process. + const std::vector<Thread>& Threads(); + + //! \brief Return a memory reader for the target process. + ProcessMemory* Memory() { return process_memory_.get(); } + + private: + //! Performs lazy initialization of the \a modules_ vector on behalf of + //! Modules(). + void InitializeModules(); + + //! Performs lazy initialization of the \a threads_ vector on behalf of + //! Threads(). + void InitializeThreads(); + + std::vector<Module> modules_; + std::vector<Thread> threads_; + std::vector<std::unique_ptr<ElfImageReader>> module_readers_; + std::vector<std::unique_ptr<ProcessMemoryRange>> process_memory_ranges_; + std::unique_ptr<ProcessMemoryFuchsia> process_memory_; + zx_handle_t process_; + bool initialized_modules_ = false; + bool initialized_threads_ = false; + InitializationStateDcheck initialized_; + + DISALLOW_COPY_AND_ASSIGN(ProcessReaderFuchsia); +}; + +} // namespace crashpad + +#endif // CRASHPAD_SNAPSHOT_FUCHSIA_PROCESS_READER_H_
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia_test.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia_test.cc new file mode 100644 index 0000000..35af291 --- /dev/null +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_reader_fuchsia_test.cc
@@ -0,0 +1,95 @@ +// Copyright 2018 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/fuchsia/process_reader_fuchsia.h" + +#include <zircon/process.h> +#include <zircon/syscalls.h> + +#include "gtest/gtest.h" +#include "test/multiprocess_exec.h" + +namespace crashpad { +namespace test { +namespace { + +TEST(ProcessReaderFuchsia, SelfBasic) { + ProcessReaderFuchsia process_reader; + ASSERT_TRUE(process_reader.Initialize(zx_process_self())); + + static constexpr char kTestMemory[] = "Some test memory"; + char buffer[arraysize(kTestMemory)]; + ASSERT_TRUE(process_reader.Memory()->Read( + reinterpret_cast<zx_vaddr_t>(kTestMemory), sizeof(kTestMemory), &buffer)); + EXPECT_STREQ(kTestMemory, buffer); + + const auto& modules = process_reader.Modules(); + EXPECT_GT(modules.size(), 0u); + for (const auto& module : modules) { + EXPECT_FALSE(module.name.empty()); + EXPECT_NE(module.type, ModuleSnapshot::kModuleTypeUnknown); + } + + const auto& threads = process_reader.Threads(); + EXPECT_GT(threads.size(), 0u); + + zx_info_handle_basic_t info; + ASSERT_EQ(zx_object_get_info(zx_thread_self(), + ZX_INFO_HANDLE_BASIC, + &info, + sizeof(info), + nullptr, + nullptr), + ZX_OK); + EXPECT_EQ(threads[0].id, info.koid); + EXPECT_EQ(threads[0].state, ZX_THREAD_STATE_RUNNING); + EXPECT_EQ(threads[0].name, "initial-thread"); +} + +constexpr char kTestMemory[] = "Read me from another process"; + +CRASHPAD_CHILD_TEST_MAIN(ProcessReaderBasicChildTestMain) { + CheckedReadFileAtEOF(StdioFileHandle(StdioStream::kStandardInput)); + return 0; +} + +class BasicChildTest : public MultiprocessExec { + public: + BasicChildTest() : MultiprocessExec() { + SetChildTestMainFunction("ProcessReaderBasicChildTestMain"); + } + ~BasicChildTest() {} + + private: + void MultiprocessParent() override { + ProcessReaderFuchsia process_reader; + ASSERT_TRUE(process_reader.Initialize(zx_process_self())); + + std::string read_string; + ASSERT_TRUE(process_reader.Memory()->ReadCString( + reinterpret_cast<zx_vaddr_t>(kTestMemory), &read_string)); + EXPECT_EQ(read_string, kTestMemory); + } + + DISALLOW_COPY_AND_ASSIGN(BasicChildTest); +}; + +TEST(ProcessReaderFuchsia, ChildBasic) { + BasicChildTest test; + test.Run(); +} + +} // namespace +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.cc index acd5449..9d0897d 100644 --- a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.cc +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.cc
@@ -23,92 +23,175 @@ ProcessSnapshotFuchsia::~ProcessSnapshotFuchsia() {} bool ProcessSnapshotFuchsia::Initialize(zx_handle_t process) { - NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 - return false; + INITIALIZATION_STATE_SET_INITIALIZING(initialized_); + + if (!process_reader_.Initialize(process)) { + return false; + } + + InitializeThreads(); + InitializeModules(); + + INITIALIZATION_STATE_SET_VALID(initialized_); + return true; } void ProcessSnapshotFuchsia::GetCrashpadOptions( CrashpadInfoClientOptions* options) { - NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + CrashpadInfoClientOptions local_options; + + for (const auto& module : modules_) { + CrashpadInfoClientOptions module_options; + module->GetCrashpadOptions(&module_options); + + if (local_options.crashpad_handler_behavior == TriState::kUnset) { + local_options.crashpad_handler_behavior = + module_options.crashpad_handler_behavior; + } + if (local_options.system_crash_reporter_forwarding == TriState::kUnset) { + local_options.system_crash_reporter_forwarding = + module_options.system_crash_reporter_forwarding; + } + if (local_options.gather_indirectly_referenced_memory == TriState::kUnset) { + local_options.gather_indirectly_referenced_memory = + module_options.gather_indirectly_referenced_memory; + local_options.indirectly_referenced_memory_cap = + module_options.indirectly_referenced_memory_cap; + } + + // If non-default values have been found for all options, the loop can end + // early. + if (local_options.crashpad_handler_behavior != TriState::kUnset && + local_options.system_crash_reporter_forwarding != TriState::kUnset && + local_options.gather_indirectly_referenced_memory != TriState::kUnset) { + break; + } + } + + *options = local_options; } pid_t ProcessSnapshotFuchsia::ProcessID() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 return 0; } pid_t ProcessSnapshotFuchsia::ParentProcessID() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 return 0; } void ProcessSnapshotFuchsia::SnapshotTime(timeval* snapshot_time) const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 } void ProcessSnapshotFuchsia::ProcessStartTime(timeval* start_time) const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 } void ProcessSnapshotFuchsia::ProcessCPUTimes(timeval* user_time, timeval* system_time) const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 } void ProcessSnapshotFuchsia::ReportID(UUID* report_id) const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 } void ProcessSnapshotFuchsia::ClientID(UUID* client_id) const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 } const std::map<std::string, std::string>& ProcessSnapshotFuchsia::AnnotationsSimpleMap() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 return annotations_simple_map_; } const SystemSnapshot* ProcessSnapshotFuchsia::System() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 return nullptr; } std::vector<const ThreadSnapshot*> ProcessSnapshotFuchsia::Threads() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 return std::vector<const ThreadSnapshot*>(); } std::vector<const ModuleSnapshot*> ProcessSnapshotFuchsia::Modules() const { - NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 - return std::vector<const ModuleSnapshot*>(); + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + std::vector<const ModuleSnapshot*> modules; + for (const auto& module : modules_) { + modules.push_back(module.get()); + } + return modules; } std::vector<UnloadedModuleSnapshot> ProcessSnapshotFuchsia::UnloadedModules() const { - NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + // dlclose() never unloads on Fuchsia. ZX-1728 upstream. return std::vector<UnloadedModuleSnapshot>(); } const ExceptionSnapshot* ProcessSnapshotFuchsia::Exception() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 return nullptr; } std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotFuchsia::MemoryMap() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 return std::vector<const MemoryMapRegionSnapshot*>(); } std::vector<HandleSnapshot> ProcessSnapshotFuchsia::Handles() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 return std::vector<HandleSnapshot>(); } std::vector<const MemorySnapshot*> ProcessSnapshotFuchsia::ExtraMemory() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 return std::vector<const MemorySnapshot*>(); } +void ProcessSnapshotFuchsia::InitializeThreads() { + const std::vector<ProcessReaderFuchsia::Thread>& process_reader_threads = + process_reader_.Threads(); + for (const ProcessReaderFuchsia::Thread& process_reader_thread : + process_reader_threads) { + auto thread = std::make_unique<internal::ThreadSnapshotFuchsia>(); + if (thread->Initialize(&process_reader_, process_reader_thread)) { + threads_.push_back(std::move(thread)); + } + } +} + +void ProcessSnapshotFuchsia::InitializeModules() { + for (const ProcessReaderFuchsia::Module& reader_module : + process_reader_.Modules()) { + auto module = std::make_unique<internal::ModuleSnapshotElf>( + reader_module.name, reader_module.reader, reader_module.type); + if (module->Initialize()) { + modules_.push_back(std::move(module)); + } + } +} + } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.h b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.h index 5ae6fd3..eb07733 100644 --- a/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.h +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/process_snapshot_fuchsia.h
@@ -17,10 +17,18 @@ #include <zircon/types.h> +#include <memory> +#include <vector> + #include "base/macros.h" #include "snapshot/crashpad_info_client_options.h" +#include "snapshot/elf/elf_image_reader.h" +#include "snapshot/elf/module_snapshot_elf.h" +#include "snapshot/fuchsia/process_reader_fuchsia.h" +#include "snapshot/fuchsia/thread_snapshot_fuchsia.h" #include "snapshot/process_snapshot.h" #include "snapshot/unloaded_module_snapshot.h" +#include "util/misc/initialization_state_dcheck.h" namespace crashpad { @@ -66,7 +74,17 @@ std::vector<const MemorySnapshot*> ExtraMemory() const override; private: + // Initializes threads_ on behalf of Initialize(). + void InitializeThreads(); + + // Initializes modules_ on behalf of Initialize(). + void InitializeModules(); + + std::vector<std::unique_ptr<internal::ThreadSnapshotFuchsia>> threads_; + std::vector<std::unique_ptr<internal::ModuleSnapshotElf>> modules_; + ProcessReaderFuchsia process_reader_; std::map<std::string, std::string> annotations_simple_map_; + InitializationStateDcheck initialized_; DISALLOW_COPY_AND_ASSIGN(ProcessSnapshotFuchsia); };
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/thread_snapshot_fuchsia.cc b/third_party/crashpad/crashpad/snapshot/fuchsia/thread_snapshot_fuchsia.cc new file mode 100644 index 0000000..ce1aeb33 --- /dev/null +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/thread_snapshot_fuchsia.cc
@@ -0,0 +1,96 @@ +// Copyright 2018 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/fuchsia/thread_snapshot_fuchsia.h" + +#include "base/logging.h" + +namespace crashpad { +namespace internal { + +ThreadSnapshotFuchsia::ThreadSnapshotFuchsia() + : ThreadSnapshot(), + context_arch_(), + context_(), + stack_(), + thread_id_(ZX_KOID_INVALID), + thread_specific_data_address_(0), + initialized_() {} + +ThreadSnapshotFuchsia::~ThreadSnapshotFuchsia() {} + +bool ThreadSnapshotFuchsia::Initialize( + ProcessReaderFuchsia* process_reader, + const ProcessReaderFuchsia::Thread& thread) { + INITIALIZATION_STATE_SET_INITIALIZING(initialized_); + +#if defined(ARCH_CPU_X86_64) + context_.architecture = kCPUArchitectureX86_64; + context_.x86_64 = &context_arch_; +// TODO(scottmg): Implement context capture for x64. +#elif defined(ARCH_CPU_ARM64) + context_.architecture = kCPUArchitectureARM64; + context_.arm64 = &context_arch_; +// TODO(scottmg): Implement context capture for arm64. +#else +#error Port. +#endif + + // TODO(scottmg): https://crashpad.chromium.org/bug/196. Initialize stack_ and + // TLS address here. API request for stack range filed upstream at ZX-1748. + + thread_id_ = thread.id; + + INITIALIZATION_STATE_SET_VALID(initialized_); + return true; +} + +const CPUContext* ThreadSnapshotFuchsia::Context() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return &context_; +} + +const MemorySnapshot* ThreadSnapshotFuchsia::Stack() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return &stack_; +} + +uint64_t ThreadSnapshotFuchsia::ThreadID() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return thread_id_; +} + +int ThreadSnapshotFuchsia::SuspendCount() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + // There is not (currently) a suspend count for threads on Fuchsia. + return 0; +} + +int ThreadSnapshotFuchsia::Priority() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + // There is not (currently) thread priorities on Fuchsia. + return 0; +} + +uint64_t ThreadSnapshotFuchsia::ThreadSpecificDataAddress() const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return thread_specific_data_address_; +} + +std::vector<const MemorySnapshot*> ThreadSnapshotFuchsia::ExtraMemory() const { + return std::vector<const MemorySnapshot*>(); +} + +} // namespace internal +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/fuchsia/thread_snapshot_fuchsia.h b/third_party/crashpad/crashpad/snapshot/fuchsia/thread_snapshot_fuchsia.h new file mode 100644 index 0000000..db975976 --- /dev/null +++ b/third_party/crashpad/crashpad/snapshot/fuchsia/thread_snapshot_fuchsia.h
@@ -0,0 +1,81 @@ +// Copyright 2018 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_FUCHSIA_THREAD_SNAPSHOT_FUCHSIA_H_ +#define CRASHPAD_SNAPSHOT_FUCHSIA_THREAD_SNAPSHOT_FUCHSIA_H_ + +#include <stdint.h> +#include <zircon/types.h> + +#include "base/macros.h" +#include "build/build_config.h" +#include "snapshot/cpu_context.h" +#include "snapshot/fuchsia/process_reader_fuchsia.h" +#include "snapshot/memory_snapshot.h" +#include "snapshot/memory_snapshot_generic.h" +#include "snapshot/thread_snapshot.h" +#include "util/misc/initialization_state_dcheck.h" + +namespace crashpad { +namespace internal { + +//! \brief A ThreadSnapshot of a thread on a Fuchsia system. +class ThreadSnapshotFuchsia final : public ThreadSnapshot { + public: + ThreadSnapshotFuchsia(); + ~ThreadSnapshotFuchsia() override; + + //! \brief Initializes the object. + //! + //! \param[in] process_reader A ProcessReaderFuchsia for the process + //! containing the thread. + //! \param[in] thread The thread within the ProcessReaderFuchsia for + //! which the snapshot should be created. + //! + //! \return `true` if the snapshot could be created, `false` otherwise with + //! a message logged. + bool Initialize(ProcessReaderFuchsia* process_reader, + const ProcessReaderFuchsia::Thread& thread); + + // ThreadSnapshot: + + const CPUContext* Context() const override; + const MemorySnapshot* Stack() const override; + uint64_t ThreadID() const override; + int SuspendCount() const override; + int Priority() const override; + uint64_t ThreadSpecificDataAddress() const override; + std::vector<const MemorySnapshot*> ExtraMemory() const override; + + private: +#if defined(ARCH_CPU_X86_64) + CPUContextX86_64 context_arch_; +#elif defined(ARCH_CPU_ARM64) + CPUContextARM64 context_arch_; +#else +#error Port. +#endif + CPUContext context_; + MemorySnapshotGeneric<ProcessReaderFuchsia> stack_; + zx_koid_t thread_id_; + zx_vaddr_t thread_specific_data_address_; + InitializationStateDcheck initialized_; + + DISALLOW_COPY_AND_ASSIGN(ThreadSnapshotFuchsia); +}; + +} // namespace internal +} // namespace crashpad + +#endif // CRASHPAD_SNAPSHOT_FUCHSIA_THREAD_SNAPSHOT_FUCHSIA_H_
diff --git a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc index 498b1f79..fa2e8f9 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.cc
@@ -18,7 +18,7 @@ #include "base/logging.h" #include "snapshot/linux/cpu_context_linux.h" -#include "snapshot/linux/process_reader.h" +#include "snapshot/linux/process_reader_linux.h" #include "snapshot/linux/signal_context.h" #include "util/linux/traits.h" #include "util/misc/reinterpret_bytes.h" @@ -43,7 +43,7 @@ #if defined(ARCH_CPU_X86_FAMILY) template <> bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>( - ProcessReader* reader, + ProcessReaderLinux* reader, LinuxVMAddress context_address) { UContext<ContextTraits32> ucontext; if (!reader->Memory()->Read(context_address, sizeof(ucontext), &ucontext)) { @@ -79,7 +79,7 @@ template <> bool ExceptionSnapshotLinux::ReadContext<ContextTraits64>( - ProcessReader* reader, + ProcessReaderLinux* reader, LinuxVMAddress context_address) { UContext<ContextTraits64> ucontext; if (!reader->Memory()->Read(context_address, sizeof(ucontext), &ucontext)) { @@ -99,7 +99,7 @@ template <> bool ExceptionSnapshotLinux::ReadContext<ContextTraits32>( - ProcessReader* reader, + ProcessReaderLinux* reader, LinuxVMAddress context_address) { context_.architecture = kCPUArchitectureARM; context_.arm = &context_union_.arm; @@ -179,7 +179,7 @@ template <> bool ExceptionSnapshotLinux::ReadContext<ContextTraits64>( - ProcessReader* reader, + ProcessReaderLinux* reader, LinuxVMAddress context_address) { context_.architecture = kCPUArchitectureARM64; context_.arm64 = &context_union_.arm64; @@ -253,7 +253,7 @@ #endif // ARCH_CPU_X86_FAMILY -bool ExceptionSnapshotLinux::Initialize(ProcessReader* process_reader, +bool ExceptionSnapshotLinux::Initialize(ProcessReaderLinux* process_reader, LinuxVMAddress siginfo_address, LinuxVMAddress context_address, pid_t thread_id) { @@ -278,7 +278,7 @@ } template <typename Traits> -bool ExceptionSnapshotLinux::ReadSiginfo(ProcessReader* reader, +bool ExceptionSnapshotLinux::ReadSiginfo(ProcessReaderLinux* reader, LinuxVMAddress siginfo_address) { Siginfo<Traits> siginfo; if (!reader->Memory()->Read(siginfo_address, sizeof(siginfo), &siginfo)) {
diff --git a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h index 7394966..0dcead7b 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h +++ b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux.h
@@ -24,7 +24,7 @@ #include "build/build_config.h" #include "snapshot/cpu_context.h" #include "snapshot/exception_snapshot.h" -#include "snapshot/linux/process_reader.h" +#include "snapshot/linux/process_reader_linux.h" #include "snapshot/memory_snapshot.h" #include "util/linux/address_types.h" #include "util/misc/initialization_state_dcheck.h" @@ -41,7 +41,8 @@ //! \brief Initializes the object. //! - //! \param[in] process_reader A ProcessReader for the process that received + //! \param[in] process_reader A ProcessReaderLinux for the process that + //! received //! the signal. //! \param[in] siginfo_address The address in the target process' address //! space of the siginfo_t passed to the signal handler. @@ -51,7 +52,7 @@ //! //! \return `true` if the snapshot could be created, `false` otherwise with //! an appropriate message logged. - bool Initialize(ProcessReader* process_reader, + bool Initialize(ProcessReaderLinux* process_reader, LinuxVMAddress siginfo_address, LinuxVMAddress context_address, pid_t thread_id); @@ -68,10 +69,10 @@ private: template <typename Traits> - bool ReadSiginfo(ProcessReader* reader, LinuxVMAddress siginfo_address); + bool ReadSiginfo(ProcessReaderLinux* reader, LinuxVMAddress siginfo_address); template <typename Traits> - bool ReadContext(ProcessReader* reader, LinuxVMAddress context_address); + bool ReadContext(ProcessReaderLinux* reader, LinuxVMAddress context_address); union { #if defined(ARCH_CPU_X86_FAMILY)
diff --git a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc index 24f0ef5..4add607d 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/exception_snapshot_linux_test.cc
@@ -25,7 +25,7 @@ #include "base/strings/stringprintf.h" #include "gtest/gtest.h" #include "snapshot/cpu_architecture.h" -#include "snapshot/linux/process_reader.h" +#include "snapshot/linux/process_reader_linux.h" #include "snapshot/linux/signal_context.h" #include "sys/syscall.h" #include "test/errors.h" @@ -271,7 +271,7 @@ FakePtraceConnection connection; ASSERT_TRUE(connection.Initialize(getpid())); - ProcessReader process_reader; + ProcessReaderLinux process_reader; ASSERT_TRUE(process_reader.Initialize(&connection)); siginfo_t siginfo; @@ -348,7 +348,7 @@ FakePtraceConnection connection; ASSERT_TRUE(connection.Initialize(getpid())); - ProcessReader process_reader; + ProcessReaderLinux process_reader; ASSERT_TRUE(process_reader.Initialize(&connection)); internal::ExceptionSnapshotLinux exception; @@ -411,7 +411,7 @@ FakePtraceConnection connection; ASSERT_TRUE(connection.Initialize(getpid())); - ProcessReader process_reader; + ProcessReaderLinux process_reader; ASSERT_TRUE(process_reader.Initialize(&connection)); internal::ExceptionSnapshotLinux exception;
diff --git a/third_party/crashpad/crashpad/snapshot/linux/memory_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/memory_snapshot_linux.cc deleted file mode 100644 index dfe9d33..0000000 --- a/third_party/crashpad/crashpad/snapshot/linux/memory_snapshot_linux.cc +++ /dev/null
@@ -1,73 +0,0 @@ -// 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/linux/memory_snapshot_linux.h" - -#include <memory> - -namespace crashpad { -namespace internal { - -MemorySnapshotLinux::MemorySnapshotLinux() - : MemorySnapshot(), - process_reader_(nullptr), - address_(0), - size_(0), - initialized_() { -} - -MemorySnapshotLinux::~MemorySnapshotLinux() { -} - -void MemorySnapshotLinux::Initialize(ProcessReader* process_reader, - LinuxVMAddress address, - size_t size) { - INITIALIZATION_STATE_SET_INITIALIZING(initialized_); - process_reader_ = process_reader; - address_ = address; - size_ = size; - INITIALIZATION_STATE_SET_VALID(initialized_); -} - -uint64_t MemorySnapshotLinux::Address() const { - INITIALIZATION_STATE_DCHECK_VALID(initialized_); - return address_; -} - -size_t MemorySnapshotLinux::Size() const { - INITIALIZATION_STATE_DCHECK_VALID(initialized_); - return size_; -} - -bool MemorySnapshotLinux::Read(Delegate* delegate) const { - INITIALIZATION_STATE_DCHECK_VALID(initialized_); - - if (size_ == 0) { - return delegate->MemorySnapshotDelegateRead(nullptr, size_); - } - - std::unique_ptr<uint8_t[]> buffer(new uint8_t[size_]); - if (!process_reader_->Memory()->Read(address_, size_, buffer.get())) { - return false; - } - return delegate->MemorySnapshotDelegateRead(buffer.get(), size_); -} - -const MemorySnapshot* MemorySnapshotLinux::MergeWithOtherSnapshot( - const MemorySnapshot* other) const { - return MergeWithOtherSnapshotImpl(this, other); -} - -} // namespace internal -} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/linux/memory_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/linux/memory_snapshot_linux.h deleted file mode 100644 index 8b4bcf8..0000000 --- a/third_party/crashpad/crashpad/snapshot/linux/memory_snapshot_linux.h +++ /dev/null
@@ -1,76 +0,0 @@ -// 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_LINUX_MEMORY_SNAPSHOT_LINUX_H_ -#define CRASHPAD_SNAPSHOT_LINUX_MEMORY_SNAPSHOT_LINUX_H_ - -#include <stddef.h> -#include <stdint.h> - -#include "base/macros.h" -#include "snapshot/linux/process_reader.h" -#include "snapshot/memory_snapshot.h" -#include "util/linux/address_types.h" -#include "util/misc/initialization_state_dcheck.h" - -namespace crashpad { -namespace internal { - -//! \brief A MemorySnapshot of a memory region in a process on the running -//! system, when the system runs Linux. -class MemorySnapshotLinux final : public MemorySnapshot { - public: - MemorySnapshotLinux(); - ~MemorySnapshotLinux() override; - - //! \brief Initializes the object. - //! - //! Memory is read lazily. No attempt is made to read the memory snapshot data - //! until Read() is called, and the memory snapshot data is discared when - //! Read() returns. - //! - //! \param[in] process_reader A reader for the process being snapshotted. - //! \param[in] address The base address of the memory region to snapshot, in - //! the snapshot process’ address space. - //! \param[in] size The size of the memory region to snapshot. - void Initialize(ProcessReader* process_reader, - LinuxVMAddress address, - size_t size); - - // MemorySnapshot: - - uint64_t Address() const override; - size_t Size() const override; - bool Read(Delegate* delegate) const override; - const MemorySnapshot* MergeWithOtherSnapshot( - const MemorySnapshot* other) const override; - - private: - template <class T> - friend const MemorySnapshot* MergeWithOtherSnapshotImpl( - const T* self, - const MemorySnapshot* other); - - ProcessReader* process_reader_; // weak - uint64_t address_; - size_t size_; - InitializationStateDcheck initialized_; - - DISALLOW_COPY_AND_ASSIGN(MemorySnapshotLinux); -}; - -} // namespace internal -} // namespace crashpad - -#endif // CRASHPAD_SNAPSHOT_LINUX_MEMORY_SNAPSHOT_LINUX_H_
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_reader.cc b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc similarity index 91% rename from third_party/crashpad/crashpad/snapshot/linux/process_reader.cc rename to third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc index 0f196c6..40b1406 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/process_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.cc
@@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "snapshot/linux/process_reader.h" +#include "snapshot/linux/process_reader_linux.h" #include <elf.h> #include <errno.h> @@ -46,7 +46,7 @@ } // namespace -ProcessReader::Thread::Thread() +ProcessReaderLinux::Thread::Thread() : thread_info(), stack_region_address(0), stack_region_size(0), @@ -54,9 +54,10 @@ static_priority(-1), nice_value(-1) {} -ProcessReader::Thread::~Thread() {} +ProcessReaderLinux::Thread::~Thread() {} -bool ProcessReader::Thread::InitializePtrace(PtraceConnection* connection) { +bool ProcessReaderLinux::Thread::InitializePtrace( + PtraceConnection* connection) { if (!connection->GetThreadInfo(tid, &thread_info)) { return false; } @@ -89,7 +90,7 @@ return true; } -void ProcessReader::Thread::InitializeStack(ProcessReader* reader) { +void ProcessReaderLinux::Thread::InitializeStack(ProcessReaderLinux* reader) { LinuxVMAddress stack_pointer; #if defined(ARCH_CPU_X86_FAMILY) stack_pointer = reader->Is64Bit() ? thread_info.thread_context.t64.rsp @@ -169,12 +170,12 @@ } } -ProcessReader::Module::Module() +ProcessReaderLinux::Module::Module() : name(), elf_reader(nullptr), type(ModuleSnapshot::kModuleTypeUnknown) {} -ProcessReader::Module::~Module() = default; +ProcessReaderLinux::Module::~Module() = default; -ProcessReader::ProcessReader() +ProcessReaderLinux::ProcessReaderLinux() : connection_(), process_info_(), memory_map_(), @@ -187,9 +188,9 @@ initialized_modules_(false), initialized_() {} -ProcessReader::~ProcessReader() {} +ProcessReaderLinux::~ProcessReaderLinux() {} -bool ProcessReader::Initialize(PtraceConnection* connection) { +bool ProcessReaderLinux::Initialize(PtraceConnection* connection) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); DCHECK(connection); connection_ = connection; @@ -213,12 +214,13 @@ return true; } -bool ProcessReader::StartTime(timeval* start_time) const { +bool ProcessReaderLinux::StartTime(timeval* start_time) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return process_info_.StartTime(start_time); } -bool ProcessReader::CPUTimes(timeval* user_time, timeval* system_time) const { +bool ProcessReaderLinux::CPUTimes(timeval* user_time, + timeval* system_time) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); timerclear(user_time); timerclear(system_time); @@ -253,7 +255,7 @@ return true; } -const std::vector<ProcessReader::Thread>& ProcessReader::Threads() { +const std::vector<ProcessReaderLinux::Thread>& ProcessReaderLinux::Threads() { INITIALIZATION_STATE_DCHECK_VALID(initialized_); if (!initialized_threads_) { InitializeThreads(); @@ -261,7 +263,7 @@ return threads_; } -const std::vector<ProcessReader::Module>& ProcessReader::Modules() { +const std::vector<ProcessReaderLinux::Module>& ProcessReaderLinux::Modules() { INITIALIZATION_STATE_DCHECK_VALID(initialized_); if (!initialized_modules_) { InitializeModules(); @@ -269,7 +271,7 @@ return modules_; } -void ProcessReader::InitializeThreads() { +void ProcessReaderLinux::InitializeThreads() { DCHECK(threads_.empty()); pid_t pid = ProcessID(); @@ -326,7 +328,7 @@ DCHECK(main_thread_found); } -void ProcessReader::InitializeModules() { +void ProcessReaderLinux::InitializeModules() { INITIALIZATION_STATE_DCHECK_VALID(initialized_); AuxiliaryVector aux;
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_reader.h b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.h similarity index 91% rename from third_party/crashpad/crashpad/snapshot/linux/process_reader.h rename to third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.h index 59a3c7ef..2e89655 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/process_reader.h +++ b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux.h
@@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_H_ -#define CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_H_ +#ifndef CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_LINUX_H_ +#define CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_LINUX_H_ #include <sys/time.h> #include <sys/types.h> @@ -38,7 +38,7 @@ //! \brief Accesses information about another process, identified by a process //! ID. -class ProcessReader { +class ProcessReaderLinux { public: //! \brief Contains information about a thread that belongs to a process. struct Thread { @@ -54,10 +54,10 @@ int nice_value; private: - friend class ProcessReader; + friend class ProcessReaderLinux; bool InitializePtrace(PtraceConnection* connection); - void InitializeStack(ProcessReader* reader); + void InitializeStack(ProcessReaderLinux* reader); }; //! \brief Contains information about a module loaded into a process. @@ -71,7 +71,7 @@ //! \brief An image reader for the module. //! //! The lifetime of this ElfImageReader is scoped to the lifetime of the - //! ProcessReader that created it. + //! ProcessReaderLinux that created it. //! //! This field may be `nullptr` if a reader could not be created for the //! module. @@ -81,8 +81,8 @@ ModuleSnapshot::ModuleType type; }; - ProcessReader(); - ~ProcessReader(); + ProcessReaderLinux(); + ~ProcessReaderLinux(); //! \brief Initializes this object. //! @@ -152,9 +152,9 @@ bool initialized_modules_; InitializationStateDcheck initialized_; - DISALLOW_COPY_AND_ASSIGN(ProcessReader); + DISALLOW_COPY_AND_ASSIGN(ProcessReaderLinux); }; } // namespace crashpad -#endif // CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_H_ +#endif // CRASHPAD_SNAPSHOT_LINUX_PROCESS_READER_LINUX_H_
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_reader_test.cc b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc similarity index 92% rename from third_party/crashpad/crashpad/snapshot/linux/process_reader_test.cc rename to third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc index a8190b3..11a606a9 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/process_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/process_reader_linux_test.cc
@@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "snapshot/linux/process_reader.h" +#include "snapshot/linux/process_reader_linux.h" #include <errno.h> #include <link.h> @@ -55,11 +55,11 @@ return syscall(SYS_gettid); } -TEST(ProcessReader, SelfBasic) { +TEST(ProcessReaderLinux, SelfBasic) { FakePtraceConnection connection; connection.Initialize(getpid()); - ProcessReader process_reader; + ProcessReaderLinux process_reader; ASSERT_TRUE(process_reader.Initialize(&connection)); #if defined(ARCH_CPU_64_BITS) @@ -92,7 +92,7 @@ DirectPtraceConnection connection; ASSERT_TRUE(connection.Initialize(ChildPID())); - ProcessReader process_reader; + ProcessReaderLinux process_reader; ASSERT_TRUE(process_reader.Initialize(&connection)); #if !defined(ARCH_CPU_64_BITS) @@ -115,7 +115,7 @@ DISALLOW_COPY_AND_ASSIGN(BasicChildTest); }; -TEST(ProcessReader, ChildBasic) { +TEST(ProcessReaderLinux, ChildBasic) { BasicChildTest test; test.Run(); } @@ -241,7 +241,7 @@ using ThreadMap = std::map<pid_t, TestThreadPool::ThreadExpectation>; void ExpectThreads(const ThreadMap& thread_map, - const std::vector<ProcessReader::Thread>& threads, + const std::vector<ProcessReaderLinux::Thread>& threads, const pid_t pid) { ASSERT_EQ(threads.size(), thread_map.size()); MemoryMap memory_map; @@ -302,9 +302,9 @@ DirectPtraceConnection connection; ASSERT_TRUE(connection.Initialize(ChildPID())); - ProcessReader process_reader; + ProcessReaderLinux process_reader; ASSERT_TRUE(process_reader.Initialize(&connection)); - const std::vector<ProcessReader::Thread>& threads = + const std::vector<ProcessReaderLinux::Thread>& threads = process_reader.Threads(); ExpectThreads(thread_map, threads, ChildPID()); } @@ -350,12 +350,12 @@ DISALLOW_COPY_AND_ASSIGN(ChildThreadTest); }; -TEST(ProcessReader, ChildWithThreads) { +TEST(ProcessReaderLinux, ChildWithThreads) { ChildThreadTest test; test.Run(); } -TEST(ProcessReader, ChildThreadsWithSmallUserStacks) { +TEST(ProcessReaderLinux, ChildThreadsWithSmallUserStacks) { ChildThreadTest test(PTHREAD_STACK_MIN); test.Run(); } @@ -379,10 +379,10 @@ DirectPtraceConnection connection; ASSERT_TRUE(connection.Initialize(ChildPID())); - ProcessReader process_reader; + ProcessReaderLinux process_reader; ASSERT_TRUE(process_reader.Initialize(&connection)); - const std::vector<ProcessReader::Thread>& threads = + const std::vector<ProcessReaderLinux::Thread>& threads = process_reader.Threads(); ASSERT_EQ(threads.size(), 1u); @@ -440,7 +440,7 @@ DISALLOW_COPY_AND_ASSIGN(ChildWithSplitStackTest); }; -TEST(ProcessReader, ChildWithSplitStack) { +TEST(ProcessReaderLinux, ChildWithSplitStack) { ChildWithSplitStackTest test; test.Run(); } @@ -454,7 +454,7 @@ LinuxVMAddress{info->dlpi_addr}, FromPointerCast<LinuxVMAddress>(info->dlpi_phdr))); auto modules = - reinterpret_cast<const std::vector<ProcessReader::Module>*>(data); + reinterpret_cast<const std::vector<ProcessReaderLinux::Module>*>(data); auto phdr_addr = FromPointerCast<LinuxVMAddress>(info->dlpi_phdr); @@ -482,7 +482,8 @@ } #endif // !OS_ANDROID || !ARCH_CPU_ARMEL || __ANDROID_API__ >= 21 -void ExpectModulesFromSelf(const std::vector<ProcessReader::Module>& modules) { +void ExpectModulesFromSelf( + const std::vector<ProcessReaderLinux::Module>& modules) { for (const auto& module : modules) { EXPECT_FALSE(module.name.empty()); EXPECT_NE(module.type, ModuleSnapshot::kModuleTypeUnknown); @@ -490,19 +491,20 @@ // Android doesn't provide dl_iterate_phdr on ARM until API 21. #if !defined(OS_ANDROID) || !defined(ARCH_CPU_ARMEL) || __ANDROID_API__ >= 21 - EXPECT_EQ(dl_iterate_phdr( - ExpectFindModule, - reinterpret_cast<void*>( - const_cast<std::vector<ProcessReader::Module>*>(&modules))), - 0); + EXPECT_EQ( + dl_iterate_phdr( + ExpectFindModule, + reinterpret_cast<void*>( + const_cast<std::vector<ProcessReaderLinux::Module>*>(&modules))), + 0); #endif // !OS_ANDROID || !ARCH_CPU_ARMEL || __ANDROID_API__ >= 21 } -TEST(ProcessReader, SelfModules) { +TEST(ProcessReaderLinux, SelfModules) { FakePtraceConnection connection; connection.Initialize(getpid()); - ProcessReader process_reader; + ProcessReaderLinux process_reader; ASSERT_TRUE(process_reader.Initialize(&connection)); ExpectModulesFromSelf(process_reader.Modules()); @@ -518,7 +520,7 @@ DirectPtraceConnection connection; ASSERT_TRUE(connection.Initialize(ChildPID())); - ProcessReader process_reader; + ProcessReaderLinux process_reader; ASSERT_TRUE(process_reader.Initialize(&connection)); ExpectModulesFromSelf(process_reader.Modules()); @@ -529,7 +531,7 @@ DISALLOW_COPY_AND_ASSIGN(ChildModuleTest); }; -TEST(ProcessReader, ChildModules) { +TEST(ProcessReaderLinux, ChildModules) { ChildModuleTest test; test.Run(); }
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.cc index 8397ad9..9e21244 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.cc
@@ -213,9 +213,9 @@ } void ProcessSnapshotLinux::InitializeThreads() { - const std::vector<ProcessReader::Thread>& process_reader_threads = + const std::vector<ProcessReaderLinux::Thread>& process_reader_threads = process_reader_.Threads(); - for (const ProcessReader::Thread& process_reader_thread : + for (const ProcessReaderLinux::Thread& process_reader_thread : process_reader_threads) { auto thread = std::make_unique<internal::ThreadSnapshotLinux>(); if (thread->Initialize(&process_reader_, process_reader_thread)) { @@ -225,9 +225,11 @@ } void ProcessSnapshotLinux::InitializeModules() { - for (const ProcessReader::Module& reader_module : process_reader_.Modules()) { - auto module = std::make_unique<internal::ModuleSnapshotLinux>(); - if (module->Initialize(reader_module)) { + for (const ProcessReaderLinux::Module& reader_module : + process_reader_.Modules()) { + auto module = std::make_unique<internal::ModuleSnapshotElf>( + reader_module.name, reader_module.elf_reader, reader_module.type); + if (module->Initialize()) { modules_.push_back(std::move(module)); } }
diff --git a/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.h index aa6964c..25c414d 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.h +++ b/third_party/crashpad/crashpad/snapshot/linux/process_snapshot_linux.h
@@ -25,9 +25,9 @@ #include "base/macros.h" #include "snapshot/crashpad_info_client_options.h" +#include "snapshot/elf/module_snapshot_elf.h" #include "snapshot/linux/exception_snapshot_linux.h" -#include "snapshot/linux/module_snapshot_linux.h" -#include "snapshot/linux/process_reader.h" +#include "snapshot/linux/process_reader_linux.h" #include "snapshot/linux/system_snapshot_linux.h" #include "snapshot/linux/thread_snapshot_linux.h" #include "snapshot/memory_map_region_snapshot.h" @@ -124,10 +124,10 @@ UUID report_id_; UUID client_id_; std::vector<std::unique_ptr<internal::ThreadSnapshotLinux>> threads_; - std::vector<std::unique_ptr<internal::ModuleSnapshotLinux>> modules_; + std::vector<std::unique_ptr<internal::ModuleSnapshotElf>> modules_; std::unique_ptr<internal::ExceptionSnapshotLinux> exception_; internal::SystemSnapshotLinux system_; - ProcessReader process_reader_; + ProcessReaderLinux process_reader_; InitializationStateDcheck initialized_; DISALLOW_COPY_AND_ASSIGN(ProcessSnapshotLinux);
diff --git a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc index c9c6438..4c39288 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.cc
@@ -151,7 +151,7 @@ SystemSnapshotLinux::~SystemSnapshotLinux() {} -void SystemSnapshotLinux::Initialize(ProcessReader* process_reader, +void SystemSnapshotLinux::Initialize(ProcessReaderLinux* process_reader, const timeval* snapshot_time) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); process_reader_ = process_reader;
diff --git a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.h index a991450..d22c49a6 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.h +++ b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux.h
@@ -22,7 +22,7 @@ #include "base/macros.h" #include "build/build_config.h" -#include "snapshot/linux/process_reader.h" +#include "snapshot/linux/process_reader_linux.h" #include "snapshot/system_snapshot.h" #include "util/misc/initialization_state_dcheck.h" @@ -44,9 +44,9 @@ //! \param[in] process_reader A reader for the process being snapshotted. //! \n\n //! It seems odd that a system snapshot implementation would need a - //! ProcessReader, but some of the information reported about the system - //! depends on the process it’s being reported for. For example, the - //! architecture returned by GetCPUArchitecture() should be the + //! ProcessReaderLinux, but some of the information reported about the + //! system depends on the process it’s being reported for. For example, + //! the architecture returned by GetCPUArchitecture() should be the //! architecture of the process, which may be different than the native //! architecture of the system: an x86_64 system can run both x86_64 and //! 32-bit x86 processes. @@ -57,7 +57,8 @@ //! Otherwise, it would need to base its determination on the current //! time, which may be different than the snapshot time for snapshots //! generated around the daylight saving transition time. - void Initialize(ProcessReader* process_reader, const timeval* snapshot_time); + void Initialize(ProcessReaderLinux* process_reader, + const timeval* snapshot_time); // SystemSnapshot: @@ -91,7 +92,7 @@ std::string os_version_full_; std::string os_version_build_; - ProcessReader* process_reader_; // weak + ProcessReaderLinux* process_reader_; // weak const timeval* snapshot_time_; // weak #if defined(ARCH_CPU_X86_FAMILY) CpuidReader cpuid_;
diff --git a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux_test.cc b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux_test.cc index a91dfa41..46d3845f 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux_test.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/system_snapshot_linux_test.cc
@@ -21,7 +21,7 @@ #include "build/build_config.h" #include "gtest/gtest.h" -#include "snapshot/linux/process_reader.h" +#include "snapshot/linux/process_reader_linux.h" #include "test/errors.h" #include "test/linux/fake_ptrace_connection.h" @@ -33,7 +33,7 @@ FakePtraceConnection connection; ASSERT_TRUE(connection.Initialize(getpid())); - ProcessReader process_reader; + ProcessReaderLinux process_reader; ASSERT_TRUE(process_reader.Initialize(&connection)); timeval snapshot_time;
diff --git a/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc index f465a59..084ed73 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc +++ b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.cc
@@ -37,9 +37,8 @@ ThreadSnapshotLinux::~ThreadSnapshotLinux() { } -bool ThreadSnapshotLinux::Initialize( - ProcessReader* process_reader, - const ProcessReader::Thread& thread) { +bool ThreadSnapshotLinux::Initialize(ProcessReaderLinux* process_reader, + const ProcessReaderLinux::Thread& thread) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); #if defined(ARCH_CPU_X86_FAMILY)
diff --git a/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h index 1ba291d..8fc7e17 100644 --- a/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h +++ b/third_party/crashpad/crashpad/snapshot/linux/thread_snapshot_linux.h
@@ -20,9 +20,9 @@ #include "base/macros.h" #include "build/build_config.h" #include "snapshot/cpu_context.h" -#include "snapshot/linux/memory_snapshot_linux.h" -#include "snapshot/linux/process_reader.h" +#include "snapshot/linux/process_reader_linux.h" #include "snapshot/memory_snapshot.h" +#include "snapshot/memory_snapshot_generic.h" #include "snapshot/thread_snapshot.h" #include "util/misc/initialization_state_dcheck.h" @@ -37,15 +37,15 @@ //! \brief Initializes the object. //! - //! \param[in] process_reader A ProcessReader for the process containing the - //! thread. - //! \param[in] thread The thread within the ProcessReader for + //! \param[in] process_reader A ProcessReaderLinux for the process containing + //! the thread. + //! \param[in] thread The thread within the ProcessReaderLinux for //! which the snapshot should be created. //! //! \return `true` if the snapshot could be created, `false` otherwise with //! a message logged. - bool Initialize(ProcessReader* process_reader, - const ProcessReader::Thread& thread); + bool Initialize(ProcessReaderLinux* process_reader, + const ProcessReaderLinux::Thread& thread); // ThreadSnapshot: @@ -70,7 +70,7 @@ #endif // ARCH_CPU_X86_FAMILY } context_union_; CPUContext context_; - MemorySnapshotLinux stack_; + MemorySnapshotGeneric<ProcessReaderLinux> stack_; LinuxVMAddress thread_specific_data_address_; pid_t thread_id_; int priority_;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.cc index 92c8450..50d1a12 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.cc
@@ -17,7 +17,7 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" #include "snapshot/mac/cpu_context_mac.h" -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include "util/mach/exception_behaviors.h" #include "util/mach/exception_types.h" #include "util/mach/symbolic_constants_mach.h" @@ -41,7 +41,7 @@ ExceptionSnapshotMac::~ExceptionSnapshotMac() { } -bool ExceptionSnapshotMac::Initialize(ProcessReader* process_reader, +bool ExceptionSnapshotMac::Initialize(ProcessReaderMac* process_reader, exception_behavior_t behavior, thread_t exception_thread, exception_type_t exception, @@ -126,8 +126,9 @@ exception_code_0_ = unsigned_exception_code_0; } - const ProcessReader::Thread* thread = nullptr; - for (const ProcessReader::Thread& loop_thread : process_reader->Threads()) { + const ProcessReaderMac::Thread* thread = nullptr; + for (const ProcessReaderMac::Thread& loop_thread : + process_reader->Threads()) { if (exception_thread == loop_thread.port) { thread = &loop_thread; break;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.h b/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.h index 9a6ddcaa..52ef519 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.h +++ b/third_party/crashpad/crashpad/snapshot/mac/exception_snapshot_mac.h
@@ -29,7 +29,7 @@ namespace crashpad { -class ProcessReader; +class ProcessReaderMac; namespace internal { @@ -45,8 +45,8 @@ //! Other than \a process_reader, the parameters may be passed directly //! through from a Mach exception handler. //! - //! \param[in] process_reader A ProcessReader for the task that sustained the - //! exception. + //! \param[in] process_reader A ProcessReaderMac for the task that sustained + //! the exception. //! \param[in] behavior //! \param[in] exception_thread //! \param[in] exception @@ -58,7 +58,7 @@ //! //! \return `true` if the snapshot could be created, `false` otherwise with //! an appropriate message logged. - bool Initialize(ProcessReader* process_reader, + bool Initialize(ProcessReaderMac* process_reader, exception_behavior_t behavior, thread_t exception_thread, exception_type_t exception,
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 bb8f7e2..b02acae 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
@@ -24,7 +24,7 @@ #include "client/crashpad_info.h" #include "client/simple_string_dictionary.h" #include "snapshot/mac/mach_o_image_reader.h" -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include "snapshot/snapshot_constants.h" #include "util/mach/task_memory.h" #include "util/stdlib/strnlen.h" @@ -32,13 +32,12 @@ namespace crashpad { MachOImageAnnotationsReader::MachOImageAnnotationsReader( - ProcessReader* process_reader, + ProcessReaderMac* process_reader, const MachOImageReader* image_reader, const std::string& name) : name_(name), process_reader_(process_reader), - image_reader_(image_reader) { -} + image_reader_(image_reader) {} std::vector<std::string> MachOImageAnnotationsReader::Vector() const { std::vector<std::string> vector_annotations;
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 06d2bea..a56b073 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
@@ -26,7 +26,7 @@ namespace crashpad { class MachOImageReader; -class ProcessReader; +class ProcessReaderMac; //! \brief A reader for annotations stored in a Mach-O image mapped into another //! process. @@ -54,7 +54,7 @@ //! contained within the remote process. //! \param[in] name The module’s name, a string to be used in logged messages. //! This string is for diagnostic purposes only, and may be empty. - MachOImageAnnotationsReader(ProcessReader* process_reader, + MachOImageAnnotationsReader(ProcessReaderMac* process_reader, const MachOImageReader* image_reader, const std::string& name); @@ -91,7 +91,7 @@ std::vector<AnnotationSnapshot>* vector_annotations) const; std::string name_; - ProcessReader* process_reader_; // weak + ProcessReaderMac* process_reader_; // weak const MachOImageReader* image_reader_; // weak DISALLOW_COPY_AND_ASSIGN(MachOImageAnnotationsReader);
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 f486c1d..6930250 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
@@ -33,7 +33,7 @@ #include "client/crashpad_info.h" #include "client/simple_string_dictionary.h" #include "gtest/gtest.h" -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include "test/errors.h" #include "test/mac/mach_errors.h" #include "test/mac/mach_multiprocess.h" @@ -161,15 +161,15 @@ EXPECT_EQ(kr, KERN_SUCCESS) << MachErrorMessage(kr, "pid_for_task"); EXPECT_EQ(task_pid, ChildPID()); - ProcessReader process_reader; + ProcessReaderMac process_reader; bool rv = process_reader.Initialize(task); if (!rv) { ADD_FAILURE(); } else { - const std::vector<ProcessReader::Module>& modules = + const std::vector<ProcessReaderMac::Module>& modules = process_reader.Modules(); std::vector<std::string> all_annotations_vector; - for (const ProcessReader::Module& module : modules) { + for (const ProcessReaderMac::Module& module : modules) { if (module.reader) { MachOImageAnnotationsReader module_annotations_reader( &process_reader, module.reader, module.name); @@ -271,7 +271,7 @@ // MachMultiprocess: void MachMultiprocessParent() override { - ProcessReader process_reader; + ProcessReaderMac process_reader; ASSERT_TRUE(process_reader.Initialize(ChildTask())); // Wait for the child process to indicate that it’s done setting up its @@ -281,11 +281,11 @@ // Verify the “simple map” and object-based annotations set via the // CrashpadInfo interface. - const std::vector<ProcessReader::Module>& modules = + const std::vector<ProcessReaderMac::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) { + for (const ProcessReaderMac::Module& module : modules) { MachOImageAnnotationsReader module_annotations_reader( &process_reader, module.reader, module.name); std::map<std::string, std::string> module_annotations_simple_map =
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc index 8a65726..6baee770 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc
@@ -26,7 +26,7 @@ #include "client/crashpad_info.h" #include "snapshot/mac/mach_o_image_segment_reader.h" #include "snapshot/mac/mach_o_image_symbol_table_reader.h" -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include "util/mac/checked_mach_address_range.h" #include "util/misc/implicit_cast.h" @@ -62,7 +62,7 @@ MachOImageReader::~MachOImageReader() { } -bool MachOImageReader::Initialize(ProcessReader* process_reader, +bool MachOImageReader::Initialize(ProcessReaderMac* process_reader, mach_vm_address_t address, const std::string& name) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.h b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.h index c16cce9..aded956 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.h +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.h
@@ -33,7 +33,7 @@ class MachOImageSegmentReader; class MachOImageSymbolTableReader; -class ProcessReader; +class ProcessReaderMac; //! \brief A reader for Mach-O images mapped into another process. //! @@ -64,7 +64,7 @@ //! //! \return `true` if the image was read successfully, including all load //! commands. `false` otherwise, with an appropriate message logged. - bool Initialize(ProcessReader* process_reader, + bool Initialize(ProcessReaderMac* process_reader, mach_vm_address_t address, const std::string& name); @@ -337,7 +337,7 @@ mutable std::unique_ptr<MachOImageSymbolTableReader> symbol_table_; std::unique_ptr<process_types::dylib_command> id_dylib_command_; - ProcessReader* process_reader_; // weak + ProcessReaderMac* process_reader_; // weak uint32_t file_type_; InitializationStateDcheck initialized_;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc index d6b801f8..625f8a7 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc
@@ -29,7 +29,7 @@ #include "client/crashpad_info.h" #include "gtest/gtest.h" #include "snapshot/mac/mach_o_image_segment_reader.h" -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include "snapshot/mac/process_types.h" #include "test/mac/dyld.h" #include "util/misc/from_pointer_cast.h" @@ -496,7 +496,7 @@ } TEST(MachOImageReader, Self_MainExecutable) { - ProcessReader process_reader; + ProcessReaderMac process_reader; ASSERT_TRUE(process_reader.Initialize(mach_task_self())); const MachHeader* mh_execute_header = @@ -531,7 +531,7 @@ } TEST(MachOImageReader, Self_DyldImages) { - ProcessReader process_reader; + ProcessReaderMac process_reader; ASSERT_TRUE(process_reader.Initialize(mach_task_self())); uint32_t count = _dyld_image_count();
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc index 06e1daf4..1be829d 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc
@@ -20,7 +20,7 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include "util/mac/checked_mach_address_range.h" #include "util/mac/mac_util.h" #include "util/stdlib/strnlen.h" @@ -47,7 +47,7 @@ MachOImageSegmentReader::~MachOImageSegmentReader() { } -bool MachOImageSegmentReader::Initialize(ProcessReader* process_reader, +bool MachOImageSegmentReader::Initialize(ProcessReaderMac* process_reader, mach_vm_address_t load_command_address, const std::string& load_command_info, const std::string& module_name,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.h b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.h index 20f891d..bdd5771 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.h +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.h
@@ -62,7 +62,7 @@ //! //! \return `true` if the load command was read successfully. `false` //! otherwise, with an appropriate message logged. - bool Initialize(ProcessReader* process_reader, + bool Initialize(ProcessReaderMac* process_reader, mach_vm_address_t load_command_address, const std::string& load_command_info, const std::string& module_name,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.cc index c5eb196..361253ce 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.cc
@@ -39,7 +39,7 @@ class MachOImageSymbolTableReaderInitializer { public: MachOImageSymbolTableReaderInitializer( - ProcessReader* process_reader, + ProcessReaderMac* process_reader, const MachOImageSegmentReader* linkedit_segment, const std::string& module_info) : module_info_(module_info), @@ -243,7 +243,7 @@ std::string module_info_; CheckedMachAddressRange linkedit_range_; - ProcessReader* process_reader_; // weak + ProcessReaderMac* process_reader_; // weak const MachOImageSegmentReader* linkedit_segment_; // weak DISALLOW_COPY_AND_ASSIGN(MachOImageSymbolTableReaderInitializer); @@ -259,7 +259,7 @@ } bool MachOImageSymbolTableReader::Initialize( - ProcessReader* process_reader, + ProcessReaderMac* process_reader, const process_types::symtab_command* symtab_command, const process_types::dysymtab_command* dysymtab_command, const MachOImageSegmentReader* linkedit_segment,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.h b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.h index a097854..841b479a 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.h +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_symbol_table_reader.h
@@ -23,7 +23,7 @@ #include "base/macros.h" #include "snapshot/mac/mach_o_image_segment_reader.h" -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include "snapshot/mac/process_types.h" #include "util/misc/initialization_state_dcheck.h" @@ -92,7 +92,7 @@ //! //! \return `true` if the symbol table was read successfully. `false` //! otherwise, with an appropriate message logged. - bool Initialize(ProcessReader* process_reader, + bool Initialize(ProcessReaderMac* process_reader, const process_types::symtab_command* symtab_command, const process_types::dysymtab_command* dysymtab_command, const MachOImageSegmentReader* linkedit_segment,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/memory_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/memory_snapshot_mac.cc deleted file mode 100644 index ec1d460..0000000 --- a/third_party/crashpad/crashpad/snapshot/mac/memory_snapshot_mac.cc +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2014 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/mac/memory_snapshot_mac.h" - -#include <memory> - -#include "util/mach/task_memory.h" - -namespace crashpad { -namespace internal { - -MemorySnapshotMac::MemorySnapshotMac() - : MemorySnapshot(), - process_reader_(nullptr), - address_(0), - size_(0), - initialized_() { -} - -MemorySnapshotMac::~MemorySnapshotMac() { -} - -void MemorySnapshotMac::Initialize(ProcessReader* process_reader, - uint64_t address, - uint64_t size) { - INITIALIZATION_STATE_SET_INITIALIZING(initialized_); - process_reader_ = process_reader; - address_ = address; - size_ = size; - INITIALIZATION_STATE_SET_VALID(initialized_); -} - -uint64_t MemorySnapshotMac::Address() const { - INITIALIZATION_STATE_DCHECK_VALID(initialized_); - return address_; -} - -size_t MemorySnapshotMac::Size() const { - INITIALIZATION_STATE_DCHECK_VALID(initialized_); - return size_; -} - -bool MemorySnapshotMac::Read(Delegate* delegate) const { - INITIALIZATION_STATE_DCHECK_VALID(initialized_); - - if (size_ == 0) { - return delegate->MemorySnapshotDelegateRead(nullptr, size_); - } - - std::unique_ptr<uint8_t[]> buffer(new uint8_t[size_]); - if (!process_reader_->Memory()->Read(address_, size_, buffer.get())) { - return false; - } - return delegate->MemorySnapshotDelegateRead(buffer.get(), size_); -} - -const MemorySnapshot* MemorySnapshotMac::MergeWithOtherSnapshot( - const MemorySnapshot* other) const { - return MergeWithOtherSnapshotImpl(this, other); -} - -} // namespace internal -} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/snapshot/mac/memory_snapshot_mac.h b/third_party/crashpad/crashpad/snapshot/mac/memory_snapshot_mac.h deleted file mode 100644 index f06fbf47..0000000 --- a/third_party/crashpad/crashpad/snapshot/mac/memory_snapshot_mac.h +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2014 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_MAC_MEMORY_SNAPSHOT_MAC_H_ -#define CRASHPAD_SNAPSHOT_MAC_MEMORY_SNAPSHOT_MAC_H_ - -#include <stdint.h> -#include <sys/types.h> - -#include "base/macros.h" -#include "snapshot/mac/process_reader.h" -#include "snapshot/memory_snapshot.h" -#include "util/misc/initialization_state_dcheck.h" - -namespace crashpad { -namespace internal { - -//! \brief A MemorySnapshot of a memory region in a process on the running -//! system, when the system runs macOS. -class MemorySnapshotMac final : public MemorySnapshot { - public: - MemorySnapshotMac(); - ~MemorySnapshotMac() override; - - //! \brief Initializes the object. - //! - //! Memory is read lazily. No attempt is made to read the memory snapshot data - //! until Read() is called, and the memory snapshot data is discared when - //! Read() returns. - //! - //! \param[in] process_reader A reader for the process being snapshotted. - //! \param[in] address The base address of the memory region to snapshot, in - //! the snapshot process’ address space. - //! \param[in] size The size of the memory region to snapshot. - void Initialize(ProcessReader* process_reader, - uint64_t address, - uint64_t size); - - // MemorySnapshot: - - uint64_t Address() const override; - size_t Size() const override; - bool Read(Delegate* delegate) const override; - const MemorySnapshot* MergeWithOtherSnapshot( - const MemorySnapshot* other) const override; - - private: - template <class T> - friend const MemorySnapshot* MergeWithOtherSnapshotImpl( - const T* self, - const MemorySnapshot* other); - - ProcessReader* process_reader_; // weak - uint64_t address_; - uint64_t size_; - InitializationStateDcheck initialized_; - - DISALLOW_COPY_AND_ASSIGN(MemorySnapshotMac); -}; - -} // namespace internal -} // namespace crashpad - -#endif // CRASHPAD_SNAPSHOT_MAC_MEMORY_SNAPSHOT_MAC_H_
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 19c4759d..4160897 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.cc
@@ -41,8 +41,8 @@ } bool ModuleSnapshotMac::Initialize( - ProcessReader* process_reader, - const ProcessReader::Module& process_reader_module) { + ProcessReaderMac* process_reader, + const ProcessReaderMac::Module& process_reader_module) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); process_reader_ = process_reader;
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 44c07910..fe2d40a1 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.h +++ b/third_party/crashpad/crashpad/snapshot/mac/module_snapshot_mac.h
@@ -25,7 +25,7 @@ #include "base/macros.h" #include "client/crashpad_info.h" #include "snapshot/crashpad_info_client_options.h" -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include "snapshot/module_snapshot.h" #include "util/misc/initialization_state_dcheck.h" @@ -45,15 +45,15 @@ //! \brief Initializes the object. //! - //! \param[in] process_reader A ProcessReader for the task containing the + //! \param[in] process_reader A ProcessReaderMac for the task containing the //! module. - //! \param[in] process_reader_module The module within the ProcessReader for - //! which the snapshot should be created. + //! \param[in] process_reader_module The module within the ProcessReaderMac + //! for which the snapshot should be created. //! //! \return `true` if the snapshot could be created, `false` otherwise with //! an appropriate message logged. - bool Initialize(ProcessReader* process_reader, - const ProcessReader::Module& process_reader_module); + bool Initialize(ProcessReaderMac* process_reader, + const ProcessReaderMac::Module& process_reader_module); //! \brief Returns options from the module’s CrashpadInfo structure. //! @@ -87,7 +87,7 @@ std::string name_; time_t timestamp_; const MachOImageReader* mach_o_image_reader_; // weak - ProcessReader* process_reader_; // weak + ProcessReaderMac* process_reader_; // weak InitializationStateDcheck initialized_; DISALLOW_COPY_AND_ASSIGN(ModuleSnapshotMac);
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.cc similarity index 94% rename from third_party/crashpad/crashpad/snapshot/mac/process_reader.cc rename to third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.cc index 6ddcff05..e142fd2 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.cc
@@ -12,11 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include <AvailabilityMacros.h> -#include <mach/mach_vm.h> #include <mach-o/loader.h> +#include <mach/mach_vm.h> #include <algorithm> #include <utility> @@ -71,7 +71,7 @@ namespace crashpad { -ProcessReader::Thread::Thread() +ProcessReaderMac::Thread::Thread() : thread_context(), float_context(), debug_context(), @@ -81,16 +81,13 @@ thread_specific_data_address(0), port(THREAD_NULL), suspend_count(0), - priority(0) { -} + priority(0) {} -ProcessReader::Module::Module() : name(), reader(nullptr), timestamp(0) { -} +ProcessReaderMac::Module::Module() : name(), reader(nullptr), timestamp(0) {} -ProcessReader::Module::~Module() { -} +ProcessReaderMac::Module::~Module() {} -ProcessReader::ProcessReader() +ProcessReaderMac::ProcessReaderMac() : process_info_(), threads_(), modules_(), @@ -100,17 +97,16 @@ initialized_(), is_64_bit_(false), initialized_threads_(false), - initialized_modules_(false) { -} + initialized_modules_(false) {} -ProcessReader::~ProcessReader() { +ProcessReaderMac::~ProcessReaderMac() { for (const Thread& thread : threads_) { kern_return_t kr = mach_port_deallocate(mach_task_self(), thread.port); MACH_LOG_IF(ERROR, kr != KERN_SUCCESS, kr) << "mach_port_deallocate"; } } -bool ProcessReader::Initialize(task_t task) { +bool ProcessReaderMac::Initialize(task_t task) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); if (!process_info_.InitializeWithTask(task)) { @@ -126,12 +122,13 @@ return true; } -void ProcessReader::StartTime(timeval* start_time) const { +void ProcessReaderMac::StartTime(timeval* start_time) const { bool rv = process_info_.StartTime(start_time); DCHECK(rv); } -bool ProcessReader::CPUTimes(timeval* user_time, timeval* system_time) const { +bool ProcessReaderMac::CPUTimes(timeval* user_time, + timeval* system_time) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); // Calculate user and system time the same way the kernel does for @@ -177,7 +174,7 @@ return true; } -const std::vector<ProcessReader::Thread>& ProcessReader::Threads() { +const std::vector<ProcessReaderMac::Thread>& ProcessReaderMac::Threads() { INITIALIZATION_STATE_DCHECK_VALID(initialized_); if (!initialized_threads_) { @@ -187,7 +184,7 @@ return threads_; } -const std::vector<ProcessReader::Module>& ProcessReader::Modules() { +const std::vector<ProcessReaderMac::Module>& ProcessReaderMac::Modules() { INITIALIZATION_STATE_DCHECK_VALID(initialized_); if (!initialized_modules_) { @@ -197,7 +194,7 @@ return modules_; } -mach_vm_address_t ProcessReader::DyldAllImageInfo( +mach_vm_address_t ProcessReaderMac::DyldAllImageInfo( mach_vm_size_t* all_image_info_size) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); @@ -210,9 +207,9 @@ return 0; } - // TODO(mark): Deal with statically linked executables which don’t use dyld. - // This may look for the module that matches the executable path in the same - // data set that vmmap uses. +// TODO(mark): Deal with statically linked executables which don’t use dyld. +// This may look for the module that matches the executable path in the same +// data set that vmmap uses. #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 // The task_dyld_info_data_t struct grew in 10.7, adding the format field. @@ -237,7 +234,7 @@ return dyld_info.all_image_info_addr; } -void ProcessReader::InitializeThreads() { +void ProcessReaderMac::InitializeThreads() { DCHECK(!initialized_threads_); DCHECK(threads_.empty()); @@ -378,7 +375,7 @@ threads_need_owners.Disarm(); } -void ProcessReader::InitializeModules() { +void ProcessReaderMac::InitializeModules() { DCHECK(!initialized_modules_); DCHECK(modules_.empty()); @@ -465,8 +462,8 @@ image_info.imageLoadAddress == all_image_infos.dyldImageLoadAddress) { found_dyld = true; LOG(WARNING) << base::StringPrintf( - "found dylinker (%s) in dyld_all_image_infos::infoArray", - module.name.c_str()); + "found dylinker (%s) in dyld_all_image_infos::infoArray", + module.name.c_str()); LOG_IF(WARNING, file_type != MH_DYLINKER) << base::StringPrintf("dylinker (%s) has unexpected Mach-O type %d", @@ -563,7 +560,7 @@ } } -mach_vm_address_t ProcessReader::CalculateStackRegion( +mach_vm_address_t ProcessReaderMac::CalculateStackRegion( mach_vm_address_t stack_pointer, mach_vm_size_t* stack_region_size) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); @@ -675,10 +672,10 @@ return region_base; } -void ProcessReader::LocateRedZone(mach_vm_address_t* const start_address, - mach_vm_address_t* const region_base, - mach_vm_address_t* const region_size, - const unsigned int user_tag) { +void ProcessReaderMac::LocateRedZone(mach_vm_address_t* const start_address, + mach_vm_address_t* const region_base, + mach_vm_address_t* const region_size, + const unsigned int user_tag) { #if defined(ARCH_CPU_X86_FAMILY) if (Is64Bit()) { // x86_64 has a red zone. See AMD64 ABI 0.99.8,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader.h b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.h similarity index 96% rename from third_party/crashpad/crashpad/snapshot/mac/process_reader.h rename to third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.h index ecca2a5..91836db 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_reader.h +++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.h
@@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_H_ -#define CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_H_ +#ifndef CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_MAC_H_ +#define CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_MAC_H_ #include <mach/mach.h> #include <stdint.h> @@ -37,7 +37,7 @@ //! \brief Accesses information about another process, identified by a Mach //! task. -class ProcessReader { +class ProcessReaderMac { public: //! \brief Contains information about a thread that belongs to a task //! (process). @@ -83,7 +83,7 @@ //! \brief An image reader for the module. //! //! The lifetime of this MachOImageReader is scoped to the lifetime of the - //! ProcessReader that created it. + //! ProcessReaderMac that created it. //! //! This field may be `nullptr` if a reader could not be created for the //! module. @@ -97,8 +97,8 @@ time_t timestamp; }; - ProcessReader(); - ~ProcessReader(); + ProcessReaderMac(); + ~ProcessReaderMac(); //! \brief Initializes this object. This method must be called before any //! other. @@ -244,9 +244,9 @@ bool initialized_threads_; bool initialized_modules_; - DISALLOW_COPY_AND_ASSIGN(ProcessReader); + DISALLOW_COPY_AND_ASSIGN(ProcessReaderMac); }; } // namespace crashpad -#endif // CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_H_ +#endif // CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_MAC_H_
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc similarity index 88% rename from third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc rename to third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc index c9f39e715..faec147 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc
@@ -12,13 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include <AvailabilityMacros.h> +#include <OpenCL/opencl.h> #include <mach-o/dyld.h> #include <mach-o/dyld_images.h> #include <mach/mach.h> -#include <OpenCL/opencl.h> #include <string.h> #include <sys/stat.h> @@ -48,8 +48,8 @@ constexpr char kDyldPath[] = "/usr/lib/dyld"; -TEST(ProcessReader, SelfBasic) { - ProcessReader process_reader; +TEST(ProcessReaderMac, SelfBasic) { + ProcessReaderMac process_reader; ASSERT_TRUE(process_reader.Initialize(mach_task_self())); #if !defined(ARCH_CPU_64_BITS) @@ -80,7 +80,7 @@ private: void MachMultiprocessParent() override { - ProcessReader process_reader; + ProcessReaderMac process_reader; ASSERT_TRUE(process_reader.Initialize(ChildTask())); #if !defined(ARCH_CPU_64_BITS) @@ -116,7 +116,7 @@ DISALLOW_COPY_AND_ASSIGN(ProcessReaderChild); }; -TEST(ProcessReader, ChildBasic) { +TEST(ProcessReaderMac, ChildBasic) { ProcessReaderChild process_reader_child; process_reader_child.Run(); } @@ -131,11 +131,12 @@ return thread_id; } -TEST(ProcessReader, SelfOneThread) { - ProcessReader process_reader; +TEST(ProcessReaderMac, SelfOneThread) { + ProcessReaderMac process_reader; ASSERT_TRUE(process_reader.Initialize(mach_task_self())); - const std::vector<ProcessReader::Thread>& threads = process_reader.Threads(); + const std::vector<ProcessReaderMac::Thread>& threads = + process_reader.Threads(); // If other tests ran in this process previously, threads may have been // created and may still be running. This check must look for at least one @@ -157,8 +158,7 @@ int suspend_count; }; - TestThreadPool() : thread_infos_() { - } + TestThreadPool() : thread_infos_() {} // Resumes suspended threads, signals each thread’s exit semaphore asking it // to exit, and joins each thread, blocking until they have all exited. @@ -192,10 +192,8 @@ thread_infos_.push_back(std::make_unique<ThreadInfo>()); ThreadInfo* thread_info = thread_infos_.back().get(); - int rv = pthread_create(&thread_info->pthread, - nullptr, - ThreadMain, - thread_info); + int rv = pthread_create( + &thread_info->pthread, nullptr, ThreadMain, thread_info); ASSERT_EQ(rv, 0); } @@ -210,8 +208,7 @@ ++thread_index) { thread_t thread_port = pthread_mach_thread_np(thread_infos_[thread_index]->pthread); - for (size_t suspend_count = 0; - suspend_count < thread_index; + for (size_t suspend_count = 0; suspend_count < thread_index; ++suspend_count) { kern_return_t kr = thread_suspend(thread_port); EXPECT_EQ(kr, KERN_SUCCESS) << MachErrorMessage(kr, "thread_suspend"); @@ -222,8 +219,7 @@ } } - uint64_t GetThreadInfo(size_t thread_index, - ThreadExpectation* expectation) { + uint64_t GetThreadInfo(size_t thread_index, ThreadExpectation* expectation) { CHECK_LT(thread_index, thread_infos_.size()); const auto& thread_info = thread_infos_[thread_index]; @@ -240,8 +236,7 @@ stack_address(0), ready_semaphore(0), exit_semaphore(0), - suspend_count(0) { - } + suspend_count(0) {} ~ThreadInfo() {} @@ -294,14 +289,14 @@ using ThreadMap = std::map<uint64_t, TestThreadPool::ThreadExpectation>; -// Verifies that all of the threads in |threads|, obtained from ProcessReader, -// agree with the expectation in |thread_map|. If |tolerate_extra_threads| is -// true, |threads| is allowed to contain threads that are not listed in -// |thread_map|. This is useful when testing situations where code outside of -// the test’s control (such as system libraries) may start threads, or may have -// started threads prior to a test’s execution. +// Verifies that all of the threads in |threads|, obtained from +// ProcessReaderMac, agree with the expectation in |thread_map|. If +// |tolerate_extra_threads| is true, |threads| is allowed to contain threads +// that are not listed in |thread_map|. This is useful when testing situations +// where code outside of the test’s control (such as system libraries) may start +// threads, or may have started threads prior to a test’s execution. void ExpectSeveralThreads(ThreadMap* thread_map, - const std::vector<ProcessReader::Thread>& threads, + const std::vector<ProcessReaderMac::Thread>& threads, const bool tolerate_extra_threads) { if (tolerate_extra_threads) { ASSERT_GE(threads.size(), thread_map->size()); @@ -310,7 +305,7 @@ } for (size_t thread_index = 0; thread_index < threads.size(); ++thread_index) { - const ProcessReader::Thread& thread = threads[thread_index]; + const ProcessReaderMac::Thread& thread = threads[thread_index]; mach_vm_address_t thread_stack_region_end = thread.stack_region_address + thread.stack_region_size; @@ -336,26 +331,26 @@ // with any other thread’s. Each thread should have a unique value for its // ID and port, and each should have its own stack that doesn’t touch any // other thread’s stack. - for (size_t other_thread_index = 0; - other_thread_index < threads.size(); + for (size_t other_thread_index = 0; other_thread_index < threads.size(); ++other_thread_index) { if (other_thread_index == thread_index) { continue; } - const ProcessReader::Thread& other_thread = threads[other_thread_index]; + const ProcessReaderMac::Thread& other_thread = + threads[other_thread_index]; EXPECT_NE(other_thread.id, thread.id); EXPECT_NE(other_thread.port, thread.port); mach_vm_address_t other_thread_stack_region_end = other_thread.stack_region_address + other_thread.stack_region_size; - EXPECT_FALSE( - thread.stack_region_address >= other_thread.stack_region_address && - thread.stack_region_address < other_thread_stack_region_end); - EXPECT_FALSE( - thread_stack_region_end > other_thread.stack_region_address && - thread_stack_region_end <= other_thread_stack_region_end); + EXPECT_FALSE(thread.stack_region_address >= + other_thread.stack_region_address && + thread.stack_region_address < other_thread_stack_region_end); + EXPECT_FALSE(thread_stack_region_end > + other_thread.stack_region_address && + thread_stack_region_end <= other_thread_stack_region_end); } } @@ -363,12 +358,12 @@ EXPECT_TRUE(thread_map->empty()); } -TEST(ProcessReader, SelfSeveralThreads) { - // Set up the ProcessReader here, before any other threads are running. This - // tests that the threads it returns are lazily initialized as a snapshot of - // the threads at the time of the first call to Threads(), and not at the +TEST(ProcessReaderMac, SelfSeveralThreads) { + // Set up the ProcessReaderMac here, before any other threads are running. + // This tests that the threads it returns are lazily initialized as a snapshot + // of the threads at the time of the first call to Threads(), and not at the // time the ProcessReader was created or initialized. - ProcessReader process_reader; + ProcessReaderMac process_reader; ASSERT_TRUE(process_reader.Initialize(mach_task_self())); TestThreadPool thread_pool; @@ -392,7 +387,8 @@ thread_map[thread_id] = expectation; } - const std::vector<ProcessReader::Thread>& threads = process_reader.Threads(); + const std::vector<ProcessReaderMac::Thread>& threads = + process_reader.Threads(); // Other tests that have run previously may have resulted in the creation of // threads that still exist, so pass true for |tolerate_extra_threads|. @@ -403,7 +399,7 @@ // shows up once. thread_t thread_self = MachThreadSelf(); bool found_thread_self = false; - for (const ProcessReader::Thread& thread : threads) { + for (const ProcessReaderMac::Thread& thread : threads) { if (thread.port == thread_self) { EXPECT_FALSE(found_thread_self); found_thread_self = true; @@ -416,15 +412,13 @@ class ProcessReaderThreadedChild final : public MachMultiprocess { public: explicit ProcessReaderThreadedChild(size_t thread_count) - : MachMultiprocess(), - thread_count_(thread_count) { - } + : MachMultiprocess(), thread_count_(thread_count) {} ~ProcessReaderThreadedChild() {} private: void MachMultiprocessParent() override { - ProcessReader process_reader; + ProcessReaderMac process_reader; ASSERT_TRUE(process_reader.Initialize(ChildTask())); FileHandle read_handle = ReadPipeHandle(); @@ -433,8 +427,7 @@ // addresses that should lie somewhere within each thread’s stack as values. // These IDs and addresses all come from the child process via the pipe. ThreadMap thread_map; - for (size_t thread_index = 0; - thread_index < thread_count_ + 1; + for (size_t thread_index = 0; thread_index < thread_count_ + 1; ++thread_index) { uint64_t thread_id; CheckedReadFileExactly(read_handle, &thread_id, sizeof(thread_id)); @@ -453,7 +446,8 @@ thread_map[thread_id] = expectation; } - const std::vector<ProcessReader::Thread>& threads = process_reader.Threads(); + const std::vector<ProcessReaderMac::Thread>& threads = + process_reader.Threads(); // The child shouldn’t have any threads other than its main thread and the // ones it created in its pool, so pass false for |tolerate_extra_threads|. @@ -484,8 +478,7 @@ sizeof(expectation.suspend_count)); // Write an entry for everything in the thread pool. - for (size_t thread_index = 0; - thread_index < thread_count_; + for (size_t thread_index = 0; thread_index < thread_count_; ++thread_index) { uint64_t thread_id = thread_pool.GetThreadInfo(thread_index, &expectation); @@ -509,14 +502,14 @@ DISALLOW_COPY_AND_ASSIGN(ProcessReaderThreadedChild); }; -TEST(ProcessReader, ChildOneThread) { +TEST(ProcessReaderMac, ChildOneThread) { // The main thread plus zero child threads equals one thread. constexpr size_t kChildThreads = 0; ProcessReaderThreadedChild process_reader_threaded_child(kChildThreads); process_reader_threaded_child.Run(); } -TEST(ProcessReader, ChildSeveralThreads) { +TEST(ProcessReaderMac, ChildSeveralThreads) { constexpr size_t kChildThreads = 64; ProcessReaderThreadedChild process_reader_threaded_child(kChildThreads); process_reader_threaded_child.Run(); @@ -537,10 +530,7 @@ class ScopedOpenCLNoOpKernel { public: ScopedOpenCLNoOpKernel() - : context_(nullptr), - program_(nullptr), - kernel_(nullptr) { - } + : context_(nullptr), program_(nullptr), kernel_(nullptr) {} ~ScopedOpenCLNoOpKernel() { if (kernel_) { @@ -566,10 +556,10 @@ #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. +// 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 @@ -642,15 +632,16 @@ #endif } -TEST(ProcessReader, SelfModules) { +TEST(ProcessReaderMac, SelfModules) { ScopedOpenCLNoOpKernel ensure_cl_kernels; ASSERT_NO_FATAL_FAILURE(ensure_cl_kernels.SetUp()); - ProcessReader process_reader; + ProcessReaderMac process_reader; ASSERT_TRUE(process_reader.Initialize(mach_task_self())); uint32_t dyld_image_count = _dyld_image_count(); - const std::vector<ProcessReader::Module>& modules = process_reader.Modules(); + const std::vector<ProcessReaderMac::Module>& modules = + process_reader.Modules(); // There needs to be at least an entry for the main executable, for a dylib, // and for dyld. @@ -718,10 +709,10 @@ private: void MachMultiprocessParent() override { - ProcessReader process_reader; + ProcessReaderMac process_reader; ASSERT_TRUE(process_reader.Initialize(ChildTask())); - const std::vector<ProcessReader::Module>& modules = + const std::vector<ProcessReaderMac::Module>& modules = process_reader.Modules(); // There needs to be at least an entry for the main executable, for a dylib, @@ -829,7 +820,7 @@ DISALLOW_COPY_AND_ASSIGN(ProcessReaderModulesChild); }; -TEST(ProcessReader, ChildModules) { +TEST(ProcessReaderMac, ChildModules) { ScopedOpenCLNoOpKernel ensure_cl_kernels; ASSERT_NO_FATAL_FAILURE(ensure_cl_kernels.SetUp());
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.cc index eaaf3dca..cf5233a 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.cc
@@ -218,9 +218,9 @@ } void ProcessSnapshotMac::InitializeThreads() { - const std::vector<ProcessReader::Thread>& process_reader_threads = + const std::vector<ProcessReaderMac::Thread>& process_reader_threads = process_reader_.Threads(); - for (const ProcessReader::Thread& process_reader_thread : + for (const ProcessReaderMac::Thread& process_reader_thread : process_reader_threads) { auto thread = std::make_unique<internal::ThreadSnapshotMac>(); if (thread->Initialize(&process_reader_, process_reader_thread)) { @@ -230,9 +230,9 @@ } void ProcessSnapshotMac::InitializeModules() { - const std::vector<ProcessReader::Module>& process_reader_modules = + const std::vector<ProcessReaderMac::Module>& process_reader_modules = process_reader_.Modules(); - for (const ProcessReader::Module& process_reader_module : + for (const ProcessReaderMac::Module& process_reader_module : process_reader_modules) { auto module = std::make_unique<internal::ModuleSnapshotMac>(); if (module->Initialize(&process_reader_, process_reader_module)) {
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.h b/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.h index e7195d941..06bac74 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.h +++ b/third_party/crashpad/crashpad/snapshot/mac/process_snapshot_mac.h
@@ -30,7 +30,7 @@ #include "snapshot/exception_snapshot.h" #include "snapshot/mac/exception_snapshot_mac.h" #include "snapshot/mac/module_snapshot_mac.h" -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include "snapshot/mac/system_snapshot_mac.h" #include "snapshot/mac/thread_snapshot_mac.h" #include "snapshot/memory_map_region_snapshot.h" @@ -143,7 +143,7 @@ std::vector<std::unique_ptr<internal::ThreadSnapshotMac>> threads_; std::vector<std::unique_ptr<internal::ModuleSnapshotMac>> modules_; std::unique_ptr<internal::ExceptionSnapshotMac> exception_; - ProcessReader process_reader_; + ProcessReaderMac process_reader_; UUID report_id_; UUID client_id_; std::map<std::string, std::string> annotations_simple_map_;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types.cc index 35d81db..65c39ea 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types.cc
@@ -94,7 +94,7 @@ namespace process_types { \ \ /* static */ \ - size_t struct_name::ExpectedSize(ProcessReader* process_reader) { \ + size_t struct_name::ExpectedSize(ProcessReaderMac* process_reader) { \ if (!process_reader->Is64Bit()) { \ return internal::struct_name<internal::Traits32>::Size(); \ } else { \ @@ -103,7 +103,7 @@ } \ \ /* static */ \ - bool struct_name::ReadInto(ProcessReader* process_reader, \ + bool struct_name::ReadInto(ProcessReaderMac* process_reader, \ mach_vm_address_t address, \ struct_name* generic) { \ if (!process_reader->Is64Bit()) { \ @@ -117,7 +117,7 @@ \ /* static */ \ template <typename T> \ - bool struct_name::ReadIntoInternal(ProcessReader* process_reader, \ + bool struct_name::ReadIntoInternal(ProcessReaderMac* process_reader, \ mach_vm_address_t address, \ struct_name* generic) { \ T specific; \ @@ -166,22 +166,22 @@ // implementations in snapshot/mac/process_types/custom.cc. #define PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO 1 -#define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ - namespace crashpad { \ - namespace process_types { \ - namespace internal { \ - \ - /* static */ \ - template <typename Traits> \ - bool struct_name<Traits>::ReadInto(ProcessReader* process_reader, \ - mach_vm_address_t address, \ - struct_name<Traits>* specific) { \ - return process_reader->Memory()->Read( \ - address, sizeof(*specific), specific); \ - } \ - } /* namespace internal */ \ - } /* namespace process_types */ \ - } /* namespace crashpad */ +#define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ + namespace crashpad { \ + namespace process_types { \ + namespace internal { \ + \ + /* static */ \ + template <typename Traits> \ + bool struct_name<Traits>::ReadInto(ProcessReaderMac* process_reader, \ + mach_vm_address_t address, \ + struct_name<Traits>* specific) { \ + return process_reader->Memory()->Read( \ + address, sizeof(*specific), specific); \ + } \ + } /* namespace internal */ \ + } /* namespace process_types */ \ + } /* namespace crashpad */ #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) @@ -214,7 +214,7 @@ \ /* static */ \ template <typename Traits> \ - bool struct_name<Traits>::ReadArrayInto(ProcessReader* process_reader, \ + bool struct_name<Traits>::ReadArrayInto(ProcessReaderMac* process_reader, \ mach_vm_address_t address, \ size_t count, \ struct_name<Traits>* specific) { \ @@ -225,7 +225,7 @@ } /* namespace internal */ \ \ /* static */ \ - bool struct_name::ReadArrayInto(ProcessReader* process_reader, \ + bool struct_name::ReadArrayInto(ProcessReaderMac* process_reader, \ mach_vm_address_t address, \ size_t count, \ struct_name* generic) { \ @@ -241,7 +241,7 @@ \ /* static */ \ template <typename T> \ - bool struct_name::ReadArrayIntoInternal(ProcessReader* process_reader, \ + bool struct_name::ReadArrayIntoInternal(ProcessReaderMac* process_reader, \ mach_vm_address_t address, \ size_t count, \ struct_name* generic) { \ @@ -293,7 +293,7 @@ \ /* static */ \ size_t struct_name::ExpectedSizeForVersion( \ - ProcessReader* process_reader, \ + ProcessReaderMac* process_reader, \ decltype(struct_name::version_field) version) { \ if (!process_reader->Is64Bit()) { \ return internal::struct_name< \ @@ -304,8 +304,8 @@ } \ } \ \ - } /* namespace process_types */ \ - } /* namespace crashpad */ + } /* namespace process_types */ \ + } /* namespace crashpad */ #define PROCESS_TYPE_STRUCT_SIZED(struct_name, size_field) @@ -354,7 +354,7 @@ } /* namespace internal */ \ \ /* static */ \ - size_t struct_name::MinimumSize(ProcessReader* process_reader) { \ + size_t struct_name::MinimumSize(ProcessReaderMac* process_reader) { \ if (!process_reader->Is64Bit()) { \ return internal::struct_name<internal::Traits32>::MinimumSize(); \ } else { \
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types.h b/third_party/crashpad/crashpad/snapshot/mac/process_types.h index 350b406..6a5f9c1 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types.h +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types.h
@@ -21,7 +21,7 @@ #include <stdint.h> #include <sys/types.h> -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" namespace crashpad { namespace process_types { @@ -80,14 +80,14 @@ \ /* Initializes an object with data read from |process_reader| at \ * |address|, properly genericized. */ \ - bool Read(ProcessReader* process_reader, mach_vm_address_t address) { \ + bool Read(ProcessReaderMac* process_reader, mach_vm_address_t address) { \ return ReadInto(process_reader, address, this); \ } \ \ /* Reads |count| objects from |process_reader| beginning at |address|, and \ * genericizes the objects. The caller must provide storage for |count| \ * objects in |generic|. */ \ - static bool ReadArrayInto(ProcessReader* process_reader, \ + static bool ReadArrayInto(ProcessReaderMac* process_reader, \ mach_vm_address_t address, \ size_t count, \ struct_name* generic); \ @@ -102,47 +102,48 @@ * on the process’ bitness. This can be used prior to reading any data \ * from a process. For versioned and sized structures, \ * ExpectedSizeForVersion() and MinimumSize() may also be useful. */ \ - static size_t ExpectedSize(ProcessReader* process_reader); + static size_t ExpectedSize(ProcessReaderMac* process_reader); #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) \ member_type member_name __VA_ARGS__; -#define PROCESS_TYPE_STRUCT_VERSIONED(struct_name, version_field) \ - /* Similar to ExpectedSize(), but computes the expected size of a \ - * structure based on the process’ bitness and a custom value, such as a \ - * structure version number. This can be used prior to reading any data \ - * from a process. */ \ - static size_t ExpectedSizeForVersion( \ - ProcessReader* process_reader, \ - decltype(struct_name::version_field) version); +#define PROCESS_TYPE_STRUCT_VERSIONED(struct_name, version_field) \ + /* Similar to ExpectedSize(), but computes the expected size of a \ + * structure based on the process’ bitness and a custom value, such as a \ + * structure version number. This can be used prior to reading any data \ + * from a process. */ \ + static size_t ExpectedSizeForVersion( \ + ProcessReaderMac* process_reader, \ + decltype(struct_name::version_field) version); -#define PROCESS_TYPE_STRUCT_SIZED(struct_name, size_field) \ - /* Similar to ExpectedSize(), but computes the minimum size of a \ - * structure based on the process’ bitness, typically including enough of \ - * a structure to contain its size field. This can be used prior to \ - * reading any data from a process. */ \ - static size_t MinimumSize(ProcessReader* process_reader); +#define PROCESS_TYPE_STRUCT_SIZED(struct_name, size_field) \ + /* Similar to ExpectedSize(), but computes the minimum size of a \ + * structure based on the process’ bitness, typically including enough of \ + * a structure to contain its size field. This can be used prior to \ + * reading any data from a process. */ \ + static size_t MinimumSize(ProcessReaderMac* process_reader); -#define PROCESS_TYPE_STRUCT_END(struct_name) \ - private: \ - /* The static form of Read(). Populates the struct at |generic|. */ \ - static bool ReadInto(ProcessReader* process_reader, \ - mach_vm_address_t address, \ - struct_name* generic); \ - \ - template <typename T> \ - static bool ReadIntoInternal(ProcessReader* process_reader, \ - mach_vm_address_t address, \ - struct_name* generic); \ - template <typename T> \ - static bool ReadArrayIntoInternal(ProcessReader* process_reader, \ - mach_vm_address_t address, \ - size_t count, \ - struct_name* generic); \ - size_t size_; \ - }; \ - } /* namespace process_types */ \ - } /* namespace crashpad */ +#define PROCESS_TYPE_STRUCT_END(struct_name) \ + private: \ + /* The static form of Read(). Populates the struct at |generic|. */ \ + static bool ReadInto(ProcessReaderMac* process_reader, \ + mach_vm_address_t address, \ + struct_name* generic); \ + \ + template <typename T> \ + static bool ReadIntoInternal(ProcessReaderMac* process_reader, \ + mach_vm_address_t address, \ + struct_name* generic); \ + template <typename T> \ + static bool ReadArrayIntoInternal(ProcessReaderMac* process_reader, \ + mach_vm_address_t address, \ + size_t count, \ + struct_name* generic); \ + size_t size_; \ + } \ + ; \ + } /* namespace process_types */ \ + } /* namespace crashpad */ #include "snapshot/mac/process_types/all.proctype" @@ -163,37 +164,37 @@ // remote process into the generic form. #define PROCESS_TYPE_STRUCT_DECLARE_INTERNAL 1 -#define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ - namespace crashpad { \ - namespace process_types { \ - namespace internal { \ - template <typename Traits> \ - struct struct_name { \ - public: \ - using Long = typename Traits::Long; \ - using ULong = typename Traits::ULong; \ - using Pointer = typename Traits::Pointer; \ - using IntPtr = typename Traits::IntPtr; \ - using UIntPtr = typename Traits::UIntPtr; \ - using Reserved32_32Only = typename Traits::Reserved32_32Only; \ - using Reserved32_64Only = typename Traits::Reserved32_64Only; \ - using Reserved64_64Only = typename Traits::Reserved64_64Only; \ - using Nothing = typename Traits::Nothing; \ - \ - /* Read(), ReadArrayInto(), and Size() are as in the generic user-visible \ - * struct above. */ \ - bool Read(ProcessReader* process_reader, mach_vm_address_t address) { \ - return ReadInto(process_reader, address, this); \ - } \ - static bool ReadArrayInto(ProcessReader* process_reader, \ - mach_vm_address_t address, \ - size_t count, \ - struct_name<Traits>* specific); \ - static size_t Size() { return sizeof(struct_name<Traits>); } \ - \ - /* Translates a struct from the representation used in the remote process \ - * into the generic form. */ \ - void GenericizeInto(process_types::struct_name* generic, \ +#define PROCESS_TYPE_STRUCT_BEGIN(struct_name) \ + namespace crashpad { \ + namespace process_types { \ + namespace internal { \ + template <typename Traits> \ + struct struct_name { \ + public: \ + using Long = typename Traits::Long; \ + using ULong = typename Traits::ULong; \ + using Pointer = typename Traits::Pointer; \ + using IntPtr = typename Traits::IntPtr; \ + using UIntPtr = typename Traits::UIntPtr; \ + using Reserved32_32Only = typename Traits::Reserved32_32Only; \ + using Reserved32_64Only = typename Traits::Reserved32_64Only; \ + using Reserved64_64Only = typename Traits::Reserved64_64Only; \ + using Nothing = typename Traits::Nothing; \ + \ + /* Read(), ReadArrayInto(), and Size() are as in the generic user-visible \ + * struct above. */ \ + bool Read(ProcessReaderMac* process_reader, mach_vm_address_t address) { \ + return ReadInto(process_reader, address, this); \ + } \ + static bool ReadArrayInto(ProcessReaderMac* process_reader, \ + mach_vm_address_t address, \ + size_t count, \ + struct_name<Traits>* specific); \ + static size_t Size() { return sizeof(struct_name<Traits>); } \ + \ + /* Translates a struct from the representation used in the remote process \ + * into the generic form. */ \ + void GenericizeInto(process_types::struct_name* generic, \ size_t* specific_size); #define PROCESS_TYPE_STRUCT_MEMBER(member_type, member_name, ...) \ @@ -209,16 +210,17 @@ /* MinimumSize() is as in the generic user-visible struct above. */ \ static size_t MinimumSize(); -#define PROCESS_TYPE_STRUCT_END(struct_name) \ - private: \ - /* ReadInto() is as in the generic user-visible struct above. */ \ - static bool ReadInto(ProcessReader* process_reader, \ - mach_vm_address_t address, \ - struct_name<Traits>* specific); \ - }; \ - } /* namespace internal */ \ - } /* namespace process_types */ \ - } /* namespace crashpad */ +#define PROCESS_TYPE_STRUCT_END(struct_name) \ + private: \ + /* ReadInto() is as in the generic user-visible struct above. */ \ + static bool ReadInto(ProcessReaderMac* process_reader, \ + mach_vm_address_t address, \ + struct_name<Traits>* specific); \ + } \ + ; \ + } /* namespace internal */ \ + } /* namespace process_types */ \ + } /* namespace crashpad */ #include "snapshot/mac/process_types/all.proctype"
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc index b9cb0e79..7c7b172 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc
@@ -75,7 +75,7 @@ } template <typename T> -bool ReadIntoVersioned(ProcessReader* process_reader, +bool ReadIntoVersioned(ProcessReaderMac* process_reader, mach_vm_address_t address, T* specific) { mach_vm_address_t field_address; @@ -95,7 +95,7 @@ } template <typename T> -bool ReadIntoSized(ProcessReader* process_reader, +bool ReadIntoSized(ProcessReaderMac* process_reader, mach_vm_address_t address, T* specific) { mach_vm_address_t field_address; @@ -156,7 +156,7 @@ // static template <typename Traits> bool dyld_all_image_infos<Traits>::ReadInto( - ProcessReader* process_reader, + ProcessReaderMac* process_reader, mach_vm_address_t address, dyld_all_image_infos<Traits>* specific) { return ReadIntoVersioned(process_reader, address, specific); @@ -178,7 +178,7 @@ // static template <typename Traits> bool crashreporter_annotations_t<Traits>::ReadInto( - ProcessReader* process_reader, + ProcessReaderMac* process_reader, mach_vm_address_t address, crashreporter_annotations_t<Traits>* specific) { return ReadIntoVersioned(process_reader, address, specific); @@ -186,30 +186,30 @@ // static template <typename Traits> -bool CrashpadInfo<Traits>::ReadInto(ProcessReader* process_reader, +bool CrashpadInfo<Traits>::ReadInto(ProcessReaderMac* process_reader, mach_vm_address_t address, CrashpadInfo<Traits>* specific) { return ReadIntoSized(process_reader, address, specific); } // Explicit template instantiation of the above. -#define PROCESS_TYPE_FLAVOR_TRAITS(lp_bits) \ - template size_t \ - dyld_all_image_infos<Traits##lp_bits>::ExpectedSizeForVersion( \ - decltype(dyld_all_image_infos<Traits##lp_bits>::version)); \ - template bool dyld_all_image_infos<Traits##lp_bits>::ReadInto( \ - ProcessReader*, \ - mach_vm_address_t, \ - dyld_all_image_infos<Traits##lp_bits>*); \ - template size_t \ - crashreporter_annotations_t<Traits##lp_bits>::ExpectedSizeForVersion( \ - decltype(crashreporter_annotations_t<Traits##lp_bits>::version)); \ - template bool crashreporter_annotations_t<Traits##lp_bits>::ReadInto( \ - ProcessReader*, \ - mach_vm_address_t, \ - crashreporter_annotations_t<Traits##lp_bits>*); \ - template bool CrashpadInfo<Traits##lp_bits>::ReadInto( \ - ProcessReader*, mach_vm_address_t, CrashpadInfo<Traits##lp_bits>*); +#define PROCESS_TYPE_FLAVOR_TRAITS(lp_bits) \ + template size_t \ + dyld_all_image_infos<Traits##lp_bits>::ExpectedSizeForVersion( \ + decltype(dyld_all_image_infos<Traits##lp_bits>::version)); \ + template bool dyld_all_image_infos<Traits##lp_bits>::ReadInto( \ + ProcessReaderMac*, \ + mach_vm_address_t, \ + dyld_all_image_infos<Traits##lp_bits>*); \ + template size_t \ + crashreporter_annotations_t<Traits##lp_bits>::ExpectedSizeForVersion( \ + decltype(crashreporter_annotations_t<Traits##lp_bits>::version)); \ + template bool crashreporter_annotations_t<Traits##lp_bits>::ReadInto( \ + ProcessReaderMac*, \ + mach_vm_address_t, \ + crashreporter_annotations_t<Traits##lp_bits>*); \ + template bool CrashpadInfo<Traits##lp_bits>::ReadInto( \ + ProcessReaderMac*, mach_vm_address_t, CrashpadInfo<Traits##lp_bits>*); #include "snapshot/mac/process_types/flavors.h"
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc index 8ab15c8..f116c4d 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc
@@ -101,7 +101,7 @@ } #endif - ProcessReader process_reader; + ProcessReaderMac process_reader; ASSERT_TRUE(process_reader.Initialize(mach_task_self())); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13
diff --git a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.cc index 140e7f4..21f254e 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.cc
@@ -25,7 +25,7 @@ #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "snapshot/cpu_context.h" -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include "snapshot/posix/timezone.h" #include "util/mac/mac_util.h" #include "util/numeric/in_range_cast.h" @@ -104,7 +104,7 @@ SystemSnapshotMac::~SystemSnapshotMac() { } -void SystemSnapshotMac::Initialize(ProcessReader* process_reader, +void SystemSnapshotMac::Initialize(ProcessReaderMac* process_reader, const timeval* snapshot_time) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
diff --git a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.h b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.h index 2ac2ef90..62b2ae6 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.h +++ b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.h
@@ -25,7 +25,7 @@ namespace crashpad { -class ProcessReader; +class ProcessReaderMac; namespace internal { @@ -40,9 +40,9 @@ //! \param[in] process_reader A reader for the process being snapshotted. //! \n\n //! It seems odd that a system snapshot implementation would need a - //! ProcessReader, but some of the information reported about the system - //! depends on the process it’s being reported for. For example, the - //! architecture returned by GetCPUArchitecture() should be the + //! ProcessReaderMac, but some of the information reported about the + //! system depends on the process it’s being reported for. For example, + //! the architecture returned by GetCPUArchitecture() should be the //! architecture of the process, which may be different than the native //! architecture of the system: an x86_64 system can run both x86_64 and //! 32-bit x86 processes. @@ -53,7 +53,8 @@ //! Otherwise, it would need to base its determination on the current //! time, which may be different than the snapshot time for snapshots //! generated around the daylight saving transition time. - void Initialize(ProcessReader* process_reader, const timeval* snapshot_time); + void Initialize(ProcessReaderMac* process_reader, + const timeval* snapshot_time); // SystemSnapshot: @@ -83,7 +84,7 @@ private: std::string os_version_full_; std::string os_version_build_; - ProcessReader* process_reader_; // weak + ProcessReaderMac* process_reader_; // weak const timeval* snapshot_time_; // weak int os_version_major_; int os_version_minor_;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac_test.cc b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac_test.cc index 646021b..69048eb 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac_test.cc
@@ -20,7 +20,7 @@ #include "build/build_config.h" #include "gtest/gtest.h" -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include "test/errors.h" #include "util/mac/mac_util.h" @@ -30,7 +30,7 @@ // SystemSnapshotMac objects would be cumbersome to construct in each test that // requires one, because of the repetitive and mechanical work necessary to set -// up a ProcessReader and timeval, along with the checks to verify that these +// up a ProcessReaderMac and timeval, along with the checks to verify that these // operations succeed. This test fixture class handles the initialization work // so that individual tests don’t have to. class SystemSnapshotMacTest : public testing::Test { @@ -55,7 +55,7 @@ } private: - ProcessReader process_reader_; + ProcessReaderMac process_reader_; timeval snapshot_time_; internal::SystemSnapshotMac system_snapshot_;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.cc index b042f75..f45fc41 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.cc
@@ -16,7 +16,7 @@ #include "base/logging.h" #include "snapshot/mac/cpu_context_mac.h" -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" namespace crashpad { namespace internal { @@ -38,8 +38,8 @@ } bool ThreadSnapshotMac::Initialize( - ProcessReader* process_reader, - const ProcessReader::Thread& process_reader_thread) { + ProcessReaderMac* process_reader, + const ProcessReaderMac::Thread& process_reader_thread) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); thread_ = process_reader_thread.port;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.h b/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.h index 2833443..8f5d722 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.h +++ b/third_party/crashpad/crashpad/snapshot/mac/thread_snapshot_mac.h
@@ -21,14 +21,15 @@ #include "base/macros.h" #include "build/build_config.h" #include "snapshot/cpu_context.h" -#include "snapshot/mac/memory_snapshot_mac.h" +#include "snapshot/mac/process_reader_mac.h" #include "snapshot/memory_snapshot.h" +#include "snapshot/memory_snapshot_generic.h" #include "snapshot/thread_snapshot.h" #include "util/misc/initialization_state_dcheck.h" namespace crashpad { -class ProcessReader; +class ProcessReaderMac; namespace internal { @@ -41,15 +42,15 @@ //! \brief Initializes the object. //! - //! \param[in] process_reader A ProcessReader for the task containing the + //! \param[in] process_reader A ProcessReaderMac for the task containing the //! thread. - //! \param[in] process_reader_thread The thread within the ProcessReader for - //! which the snapshot should be created. + //! \param[in] process_reader_thread The thread within the ProcessReaderMac + //! for which the snapshot should be created. //! //! \return `true` if the snapshot could be created, `false` otherwise with //! an appropriate message logged. - bool Initialize(ProcessReader* process_reader, - const ProcessReader::Thread& process_reader_thread); + bool Initialize(ProcessReaderMac* process_reader, + const ProcessReaderMac::Thread& process_reader_thread); // ThreadSnapshot: @@ -69,7 +70,7 @@ } context_union_; #endif CPUContext context_; - MemorySnapshotMac stack_; + MemorySnapshotGeneric<ProcessReaderMac> stack_; uint64_t thread_id_; uint64_t thread_specific_data_address_; thread_t thread_;
diff --git a/third_party/crashpad/crashpad/snapshot/memory_snapshot_generic.h b/third_party/crashpad/crashpad/snapshot/memory_snapshot_generic.h new file mode 100644 index 0000000..402e913 --- /dev/null +++ b/third_party/crashpad/crashpad/snapshot/memory_snapshot_generic.h
@@ -0,0 +1,107 @@ +// Copyright 2014 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_MEMORY_SNAPSHOT_GENERIC_H_ +#define CRASHPAD_SNAPSHOT_MEMORY_SNAPSHOT_GENERIC_H_ + +#include <stdint.h> +#include <sys/types.h> + +#include "base/macros.h" +#include "snapshot/memory_snapshot.h" +#include "util/misc/address_types.h" +#include "util/misc/initialization_state_dcheck.h" +#include "util/process/process_memory.h" + +namespace crashpad { +namespace internal { + +//! \brief A MemorySnapshot of a memory region in a process on the running +//! system. Used on Mac, Linux, Android, and Fuchsia, templated on the +//! platform-specific ProcessReader type. +template <class ProcessReaderType> +class MemorySnapshotGeneric final : public MemorySnapshot { + public: + MemorySnapshotGeneric() = default; + ~MemorySnapshotGeneric() = default; + + //! \brief Initializes the object. + //! + //! Memory is read lazily. No attempt is made to read the memory snapshot data + //! until Read() is called, and the memory snapshot data is discared when + //! Read() returns. + //! + //! \param[in] process_reader A reader for the process being snapshotted. + //! \param[in] address The base address of the memory region to snapshot, in + //! the snapshot process’ address space. + //! \param[in] size The size of the memory region to snapshot. + void Initialize(ProcessReaderType* process_reader, + VMAddress address, + VMSize size) { + INITIALIZATION_STATE_SET_INITIALIZING(initialized_); + process_reader_ = process_reader; + address_ = address; + size_ = size; + INITIALIZATION_STATE_SET_VALID(initialized_); + } + + // MemorySnapshot: + + uint64_t Address() const override { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return address_; + } + + size_t Size() const override { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return size_; + } + + bool Read(Delegate* delegate) const override { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + if (size_ == 0) { + return delegate->MemorySnapshotDelegateRead(nullptr, size_); + } + + std::unique_ptr<uint8_t[]> buffer(new uint8_t[size_]); + if (!process_reader_->Memory()->Read(address_, size_, buffer.get())) { + return false; + } + return delegate->MemorySnapshotDelegateRead(buffer.get(), size_); + } + + const MemorySnapshot* MergeWithOtherSnapshot( + const MemorySnapshot* other) const override { + return MergeWithOtherSnapshotImpl(this, other); + } + + private: + template <class T> + friend const MemorySnapshot* MergeWithOtherSnapshotImpl( + const T* self, + const MemorySnapshot* other); + + ProcessReaderType* process_reader_; // weak + uint64_t address_; + uint64_t size_; + InitializationStateDcheck initialized_; + + DISALLOW_COPY_AND_ASSIGN(MemorySnapshotGeneric); +}; + +} // namespace internal +} // namespace crashpad + +#endif // CRASHPAD_SNAPSHOT_GENERIC_MEMORY_SNAPSHOT_GENERIC_H_
diff --git a/third_party/crashpad/crashpad/snapshot/snapshot.gyp b/third_party/crashpad/crashpad/snapshot/snapshot.gyp index da19234..b199841 100644 --- a/third_party/crashpad/crashpad/snapshot/snapshot.gyp +++ b/third_party/crashpad/crashpad/snapshot/snapshot.gyp
@@ -49,6 +49,8 @@ 'elf/elf_image_reader.h', 'elf/elf_symbol_table_reader.cc', 'elf/elf_symbol_table_reader.h', + 'elf/module_snapshot_elf.cc', + 'elf/module_snapshot_elf.h', 'exception_snapshot.h', 'handle_snapshot.cc', 'handle_snapshot.h', @@ -58,12 +60,8 @@ 'linux/debug_rendezvous.h', 'linux/exception_snapshot_linux.cc', 'linux/exception_snapshot_linux.h', - 'linux/memory_snapshot_linux.cc', - 'linux/memory_snapshot_linux.h', - 'linux/module_snapshot_linux.cc', - 'linux/module_snapshot_linux.h', - 'linux/process_reader.cc', - 'linux/process_reader.h', + 'linux/process_reader_linux.cc', + 'linux/process_reader_linux.h', 'linux/process_snapshot_linux.cc', 'linux/process_snapshot_linux.h', 'linux/signal_context.h', @@ -83,12 +81,10 @@ 'mac/mach_o_image_segment_reader.h', 'mac/mach_o_image_symbol_table_reader.cc', 'mac/mach_o_image_symbol_table_reader.h', - 'mac/memory_snapshot_mac.cc', - 'mac/memory_snapshot_mac.h', 'mac/module_snapshot_mac.cc', 'mac/module_snapshot_mac.h', - 'mac/process_reader.cc', - 'mac/process_reader.h', + 'mac/process_reader_mac.cc', + 'mac/process_reader_mac.h', 'mac/process_snapshot_mac.cc', 'mac/process_snapshot_mac.h', 'mac/process_types.cc', @@ -110,6 +106,7 @@ 'mac/thread_snapshot_mac.h', 'memory_snapshot.cc', 'memory_snapshot.h', + 'memory_snapshot_generic.h', 'minidump/minidump_annotation_reader.cc', 'minidump/minidump_annotation_reader.h', 'minidump/minidump_simple_string_dictionary_reader.cc',
diff --git a/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp b/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp index 277bf6e..6f0fc90e 100644 --- a/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp +++ b/third_party/crashpad/crashpad/snapshot/snapshot_test.gyp
@@ -81,13 +81,13 @@ 'elf/elf_image_reader_test_note.S', 'linux/debug_rendezvous_test.cc', 'linux/exception_snapshot_linux_test.cc', - 'linux/process_reader_test.cc', + 'linux/process_reader_linux_test.cc', 'linux/system_snapshot_linux_test.cc', 'mac/cpu_context_mac_test.cc', 'mac/mach_o_image_annotations_reader_test.cc', 'mac/mach_o_image_reader_test.cc', 'mac/mach_o_image_segment_reader_test.cc', - 'mac/process_reader_test.cc', + 'mac/process_reader_mac_test.cc', 'mac/process_types_test.cc', 'mac/system_snapshot_mac_test.cc', 'minidump/process_snapshot_minidump_test.cc', @@ -182,6 +182,19 @@ 'sources': [ 'crashpad_info_size_test_module.cc', ], + 'include_dirs': [ + '..', + ], + 'conditions': [ + ['OS=="linux" or OS=="android"', { + 'sources': [ + 'crashpad_info_size_test_note.S', + ], + 'dependencies': [ + '../util/util.gyp:crashpad_util', + ], + }], + ], }, { 'target_name': 'crashpad_snapshot_test_module_small', @@ -195,6 +208,19 @@ 'sources': [ 'crashpad_info_size_test_module.cc', ], + 'include_dirs': [ + '..', + ], + 'conditions': [ + ['OS=="linux" or OS=="android"', { + 'sources': [ + 'crashpad_info_size_test_note.S', + ], + 'dependencies': [ + '../util/util.gyp:crashpad_util', + ], + }], + ], }, { 'target_name': 'crashpad_snapshot_test_both_dt_hash_styles',
diff --git a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_crashing_child.cc b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_crashing_child.cc index 146c66a..759cc13 100644 --- a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_crashing_child.cc +++ b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_crashing_child.cc
@@ -15,21 +15,12 @@ #include <intrin.h> #include <windows.h> -#include "base/files/file_path.h" #include "base/logging.h" +#include "build/build_config.h" #include "client/crashpad_client.h" -#include "util/file/file_io.h" -#include "util/misc/from_pointer_cast.h" +#include "util/misc/capture_context.h" #include "util/win/address_types.h" -namespace { - -__declspec(noinline) crashpad::WinVMAddress CurrentAddress() { - return crashpad::FromPointerCast<crashpad::WinVMAddress>(_ReturnAddress()); -} - -} // namespace - int wmain(int argc, wchar_t* argv[]) { CHECK_EQ(argc, 2); @@ -38,8 +29,25 @@ HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); PCHECK(out != INVALID_HANDLE_VALUE) << "GetStdHandle"; - crashpad::WinVMAddress break_address = CurrentAddress(); - crashpad::CheckedWriteFile(out, &break_address, sizeof(break_address)); + + CONTEXT context; + crashpad::CaptureContext(&context); +#if defined(ARCH_CPU_64_BITS) + crashpad::WinVMAddress break_address = context.Rip; +#else + crashpad::WinVMAddress break_address = context.Eip; +#endif + + // This does not used CheckedWriteFile() because at high optimization + // settings, a lot of logging code can be inlined, causing there to be a large + // number of instructions between where the IP is captured and the actual + // __debugbreak(). Instead call Windows' WriteFile() to minimize the amount of + // code here. Because the next line is going to crash in any case, there's + // minimal difference in behavior aside from an indication of what broke when + // the other end experiences a ReadFile() error. + DWORD bytes_written; + WriteFile( + out, &break_address, sizeof(break_address), &bytes_written, nullptr); __debugbreak();
diff --git a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_dump_without_crashing.cc b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_dump_without_crashing.cc index f55f503..e2c524ae 100644 --- a/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_dump_without_crashing.cc +++ b/third_party/crashpad/crashpad/snapshot/win/crashpad_snapshot_test_dump_without_crashing.cc
@@ -18,18 +18,9 @@ #include "base/logging.h" #include "client/crashpad_client.h" #include "client/simulate_crash.h" -#include "util/file/file_io.h" -#include "util/misc/from_pointer_cast.h" +#include "util/misc/capture_context.h" #include "util/win/address_types.h" -namespace { - -__declspec(noinline) crashpad::WinVMAddress CurrentAddress() { - return crashpad::FromPointerCast<crashpad::WinVMAddress>(_ReturnAddress()); -} - -} // namespace - int wmain(int argc, wchar_t* argv[]) { CHECK_EQ(argc, 2); @@ -38,8 +29,25 @@ HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); PCHECK(out != INVALID_HANDLE_VALUE) << "GetStdHandle"; - crashpad::WinVMAddress current_address = CurrentAddress(); - crashpad::CheckedWriteFile(out, ¤t_address, sizeof(current_address)); + + CONTEXT context; + crashpad::CaptureContext(&context); +#if defined(ARCH_CPU_64_BITS) + crashpad::WinVMAddress break_address = context.Rip; +#else + crashpad::WinVMAddress break_address = context.Eip; +#endif + + // This does not used CheckedWriteFile() because at high optimization + // settings, a lot of logging code can be inlined, causing there to be a large + // number of instructions between where the IP is captured and the actual + // __debugbreak(). Instead call Windows' WriteFile() to minimize the amount of + // code here. Because the next line is going to crash in any case, there's + // minimal difference in behavior aside from an indication of what broke when + // the other end experiences a ReadFile() error. + DWORD bytes_written; + WriteFile( + out, &break_address, sizeof(break_address), &bytes_written, nullptr); CRASHPAD_SIMULATE_CRASH();
diff --git a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h index 0d21668..f6e29d9 100644 --- a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h +++ b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.h
@@ -52,8 +52,8 @@ //! \brief Initializes the object. //! - //! \param[in] process_reader A ProcessReader for the process that sustained - //! the exception. + //! \param[in] process_reader A ProcessReaderWin for the process that + //! sustained the exception. //! \param[in] thread_id The thread ID in which the exception occurred. //! \param[in] exception_pointers The address of an `EXCEPTION_POINTERS` //! record in the target process, passed through from the exception
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 a1ab8c6..376de7c 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
@@ -103,7 +103,7 @@ // Verify the exception happened at the expected location with a bit of // slop space to allow for reading the current PC before the exception // happens. See TestCrashingChild(). - constexpr uint64_t kAllowedOffset = 64; + constexpr uint64_t kAllowedOffset = 100; EXPECT_GT(snapshot.Exception()->ExceptionAddress(), break_near_); EXPECT_LT(snapshot.Exception()->ExceptionAddress(), break_near_ + kAllowedOffset); @@ -204,7 +204,7 @@ // Verify the dump was captured at the expected location with some slop // space. - constexpr uint64_t kAllowedOffset = 64; + constexpr uint64_t kAllowedOffset = 100; EXPECT_GT(snapshot.Exception()->Context()->InstructionPointer(), dump_near_); EXPECT_LT(snapshot.Exception()->Context()->InstructionPointer(),
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 414f0a4..693588db0 100644 --- a/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.h +++ b/third_party/crashpad/crashpad/snapshot/win/module_snapshot_win.h
@@ -47,10 +47,10 @@ //! \brief Initializes the object. //! - //! \param[in] process_reader A ProcessReader for the task containing the - //! module. - //! \param[in] process_reader_module The module within the ProcessReader for - //! which the snapshot should be created. + //! \param[in] process_reader A ProcessReaderWin for the process containing + //! the module. + //! \param[in] process_reader_module The module within the ProcessReaderWin + //! for which the snapshot should be created. //! //! \return `true` if the snapshot could be created, `false` otherwise with //! an appropriate message logged.
diff --git a/third_party/crashpad/crashpad/snapshot/win/process_reader_win.cc b/third_party/crashpad/crashpad/snapshot/win/process_reader_win.cc index 73a0ca7..2fa0258 100644 --- a/third_party/crashpad/crashpad/snapshot/win/process_reader_win.cc +++ b/third_party/crashpad/crashpad/snapshot/win/process_reader_win.cc
@@ -21,8 +21,8 @@ #include "base/numerics/safe_conversions.h" #include "base/strings/stringprintf.h" +#include "util/misc/capture_context.h" #include "util/misc/time.h" -#include "util/win/capture_context.h" #include "util/win/nt_internals.h" #include "util/win/ntstatus_logging.h" #include "util/win/process_structs.h"
diff --git a/third_party/crashpad/crashpad/snapshot/win/system_snapshot_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/system_snapshot_win_test.cc index 4c99497..c87a6a6 100644 --- a/third_party/crashpad/crashpad/snapshot/win/system_snapshot_win_test.cc +++ b/third_party/crashpad/crashpad/snapshot/win/system_snapshot_win_test.cc
@@ -134,22 +134,24 @@ EXPECT_EQ(standard_offset_seconds % (15 * 60), 0) << "standard_offset_seconds " << standard_offset_seconds; - if (dst_status == SystemSnapshot::kDoesNotObserveDaylightSavingTime) { - EXPECT_EQ(daylight_offset_seconds, standard_offset_seconds); - EXPECT_EQ(daylight_name, standard_name); - } else { - EXPECT_EQ(daylight_offset_seconds % (15 * 60), 0) - << "daylight_offset_seconds " << daylight_offset_seconds; + // dst_status of kDoesNotObserveDaylightSavingTime can mean only that the + // adjustment is not automatic, as opposed to daylight/standard differences + // not existing at all. So it cannot be asserted that the two offsets are the + // same in that case. - // In contemporary usage, dst_delta_seconds will almost always be one hour, - // except for Lord Howe Island, Australia, which uses a 30-minute delta. - // Throughout history, other variations existed. See - // https://www.timeanddate.com/time/dst/. - int dst_delta_seconds = daylight_offset_seconds - standard_offset_seconds; - if (dst_delta_seconds != 60 * 60 && dst_delta_seconds != 30 * 60) { - FAIL() << "dst_delta_seconds " << dst_delta_seconds; - } + EXPECT_EQ(daylight_offset_seconds % (15 * 60), 0) + << "daylight_offset_seconds " << daylight_offset_seconds; + // In contemporary usage, dst_delta_seconds will almost always be one hour, + // except for Lord Howe Island, Australia, which uses a 30-minute delta. + // Throughout history, other variations existed. See + // https://www.timeanddate.com/time/dst/. + int dst_delta_seconds = daylight_offset_seconds - standard_offset_seconds; + if (dst_delta_seconds != 60 * 60 && dst_delta_seconds != 30 * 60) { + FAIL() << "dst_delta_seconds " << dst_delta_seconds; + } + + if (dst_status != SystemSnapshot::kDoesNotObserveDaylightSavingTime) { EXPECT_NE(standard_name, daylight_name); } }
diff --git a/third_party/crashpad/crashpad/test/BUILD.gn b/third_party/crashpad/crashpad/test/BUILD.gn index f754174..0808096 100644 --- a/third_party/crashpad/crashpad/test/BUILD.gn +++ b/third_party/crashpad/crashpad/test/BUILD.gn
@@ -74,8 +74,6 @@ "linux/fake_ptrace_connection.h", "linux/get_tls.cc", "linux/get_tls.h", - "linux/scoped_pr_set_ptracer.cc", - "linux/scoped_pr_set_ptracer.h", ] } @@ -96,7 +94,6 @@ if (crashpad_is_fuchsia) { sources += [ "multiprocess_exec_fuchsia.cc" ] - libs = [ "launchpad" ] } public_configs = [ "..:crashpad_config" ] @@ -121,6 +118,14 @@ "../snapshot", ] } + + if (crashpad_is_win) { + libs = [ "shell32.lib" ] + } + + if (crashpad_is_fuchsia) { + libs = [ "launchpad" ] + } } source_set("test_test") {
diff --git a/third_party/crashpad/crashpad/test/mac/dyld.cc b/third_party/crashpad/crashpad/test/mac/dyld.cc index 6fa2176..fb2156e 100644 --- a/third_party/crashpad/crashpad/test/mac/dyld.cc +++ b/third_party/crashpad/crashpad/test/mac/dyld.cc
@@ -21,7 +21,7 @@ #include <stdint.h> #include "base/logging.h" -#include "snapshot/mac/process_reader.h" +#include "snapshot/mac/process_reader_mac.h" #include "test/scoped_module_handle.h" #include "util/numeric/safe_assignment.h" @@ -74,7 +74,7 @@ #endif // On 10.13 and later, do it the hard way. - ProcessReader process_reader; + ProcessReaderMac process_reader; if (!process_reader.Initialize(mach_task_self())) { return nullptr; }
diff --git a/third_party/crashpad/crashpad/test/multiprocess.h b/third_party/crashpad/crashpad/test/multiprocess.h index 1d3ee9b..aac9288 100644 --- a/third_party/crashpad/crashpad/test/multiprocess.h +++ b/third_party/crashpad/crashpad/test/multiprocess.h
@@ -92,6 +92,12 @@ //! expected to kill the child. void SetExpectedChildTermination(TerminationReason reason, int code); +#if !defined(OS_WIN) + //! \brief Sets termination reason and code appropriately for a child that + //! terminates via `__builtin_trap()`. + void SetExpectedChildTerminationBuiltinTrap(); +#endif // !OS_WIN + protected: ~Multiprocess();
diff --git a/third_party/crashpad/crashpad/test/multiprocess_exec_fuchsia.cc b/third_party/crashpad/crashpad/test/multiprocess_exec_fuchsia.cc index e630608..7d571f9 100644 --- a/third_party/crashpad/crashpad/test/multiprocess_exec_fuchsia.cc +++ b/third_party/crashpad/crashpad/test/multiprocess_exec_fuchsia.cc
@@ -86,6 +86,10 @@ code_ = code; } +void Multiprocess::SetExpectedChildTerminationBuiltinTrap() { + SetExpectedChildTermination(kTerminationNormal, -1); +} + Multiprocess::~Multiprocess() { delete info_; }
diff --git a/third_party/crashpad/crashpad/test/multiprocess_exec_test.cc b/third_party/crashpad/crashpad/test/multiprocess_exec_test.cc index 0104b0f3..99a1b01f 100644 --- a/third_party/crashpad/crashpad/test/multiprocess_exec_test.cc +++ b/third_party/crashpad/crashpad/test/multiprocess_exec_test.cc
@@ -98,6 +98,35 @@ exec.Run(); }; +#if !defined(OS_WIN) + +CRASHPAD_CHILD_TEST_MAIN(BuiltinTrapChild) { + __builtin_trap(); + return EXIT_SUCCESS; +} + +class TestBuiltinTrapTermination final : public MultiprocessExec { + public: + TestBuiltinTrapTermination() { + SetChildTestMainFunction("BuiltinTrapChild"); + SetExpectedChildTerminationBuiltinTrap(); + } + + ~TestBuiltinTrapTermination() = default; + + private: + void MultiprocessParent() override {} + + DISALLOW_COPY_AND_ASSIGN(TestBuiltinTrapTermination); +}; + +TEST(MultiprocessExec, BuiltinTrapTermination) { + TestBuiltinTrapTermination test; + test.Run(); +} + +#endif // !OS_WIN + } // namespace } // namespace test } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/test/multiprocess_exec_test_child.cc b/third_party/crashpad/crashpad/test/multiprocess_exec_test_child.cc index f2761ea..8c77015 100644 --- a/third_party/crashpad/crashpad/test/multiprocess_exec_test_child.cc +++ b/third_party/crashpad/crashpad/test/multiprocess_exec_test_child.cc
@@ -23,7 +23,9 @@ #include "build/build_config.h" #if defined(OS_POSIX) +#if !defined(OS_FUCHSIA) #include <sys/resource.h> +#endif // !OS_FUCHSIA #include <unistd.h> #elif defined(OS_WIN) #include <windows.h>
diff --git a/third_party/crashpad/crashpad/test/multiprocess_posix.cc b/third_party/crashpad/crashpad/test/multiprocess_posix.cc index c638b48a..96b8ad2 100644 --- a/third_party/crashpad/crashpad/test/multiprocess_posix.cc +++ b/third_party/crashpad/crashpad/test/multiprocess_posix.cc
@@ -157,6 +157,14 @@ code_ = code; } +void Multiprocess::SetExpectedChildTerminationBuiltinTrap() { +#if defined(ARCH_CPU_ARM64) + SetExpectedChildTermination(kTerminationSignal, SIGTRAP); +#else + SetExpectedChildTermination(kTerminationSignal, SIGILL); +#endif +} + Multiprocess::~Multiprocess() { }
diff --git a/third_party/crashpad/crashpad/test/test.gyp b/third_party/crashpad/crashpad/test/test.gyp index a3721ef..2973708 100644 --- a/third_party/crashpad/crashpad/test/test.gyp +++ b/third_party/crashpad/crashpad/test/test.gyp
@@ -45,8 +45,6 @@ 'linux/fake_ptrace_connection.h', 'linux/get_tls.cc', 'linux/get_tls.h', - 'linux/scoped_pr_set_ptracer.cc', - 'linux/scoped_pr_set_ptracer.h', 'mac/dyld.cc', 'mac/dyld.h', 'mac/exception_swallower.cc',
diff --git a/third_party/crashpad/crashpad/test/test_paths.cc b/third_party/crashpad/crashpad/test/test_paths.cc index f6471d08..0d7db06 100644 --- a/third_party/crashpad/crashpad/test/test_paths.cc +++ b/third_party/crashpad/crashpad/test/test_paths.cc
@@ -127,6 +127,10 @@ // static base::FilePath TestPaths::ExpectedExecutableBasename( const base::FilePath::StringType& name) { +#if defined(OS_FUCHSIA) + // Apps in Fuchsia packages are always named "app". + return base::FilePath("app"); +#else // OS_FUCHSIA #if defined(CRASHPAD_IS_IN_CHROMIUM) base::FilePath::StringType executable_name( FILE_PATH_LITERAL("crashpad_tests")); @@ -139,6 +143,7 @@ #endif // OS_WIN return base::FilePath(executable_name); +#endif // OS_FUCHSIA } // static @@ -195,7 +200,11 @@ #endif // OS_WIN #if defined(OS_FUCHSIA) - directory = base::FilePath(FILE_PATH_LITERAL("/pkg/lib")); + // TODO(scottmg): .so files are currently deployed into /boot/lib, where + // they'll be found (without a path) by the loader. Application packaging + // infrastructure is in progress, so this will likely change again in the + // future. + directory = base::FilePath(); #endif break; }
diff --git a/third_party/crashpad/crashpad/third_party/fuchsia/README.crashpad b/third_party/crashpad/crashpad/third_party/fuchsia/README.crashpad index fc4a514..8bf0a91 100644 --- a/third_party/crashpad/crashpad/third_party/fuchsia/README.crashpad +++ b/third_party/crashpad/crashpad/third_party/fuchsia/README.crashpad
@@ -1,4 +1,3 @@ This directory is a placeholder for Fuchsia tools that will be downloaded by -CIPD (https://github.com/luci/luci-go/tree/master/cipd). The toolchain.ensure -files specifies which CIPD packages to retrieve, at which versions, and where -they're stored locally. The CIPD update happens as part of gclient runhooks. +CIPD (https://github.com/luci/luci-go/tree/master/cipd). The CIPD update happens +as part of gclient runhooks.
diff --git a/third_party/crashpad/crashpad/third_party/gtest/BUILD.gn b/third_party/crashpad/crashpad/third_party/gtest/BUILD.gn index 1a02611..db5f4a56 100644 --- a/third_party/crashpad/crashpad/third_party/gtest/BUILD.gn +++ b/third_party/crashpad/crashpad/third_party/gtest/BUILD.gn
@@ -138,6 +138,10 @@ ":gtest", ":gtest_main", ] + + if (crashpad_is_win) { + cflags = [ "/wd4702" ] # unreachable code + } } test("gtest_environment_test") {
diff --git a/third_party/crashpad/crashpad/third_party/linux/README.crashpad b/third_party/crashpad/crashpad/third_party/linux/README.crashpad new file mode 100644 index 0000000..8bf0a91 --- /dev/null +++ b/third_party/crashpad/crashpad/third_party/linux/README.crashpad
@@ -0,0 +1,3 @@ +This directory is a placeholder for Fuchsia tools that will be downloaded by +CIPD (https://github.com/luci/luci-go/tree/master/cipd). The CIPD update happens +as part of gclient runhooks.
diff --git a/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn b/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn index db0f99a1..0723ba3 100644 --- a/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn +++ b/third_party/crashpad/crashpad/third_party/zlib/BUILD.gn
@@ -89,6 +89,7 @@ "/wd4245", # conversion from 't1' to 't2', signed/unsigned mismatch "/wd4267", # conversion from 'size_t' to 't', possible loss of data "/wd4324", # structure was padded due to alignment specifier + "/wd4702", # unreachable code ] } else { defines += [
diff --git a/third_party/crashpad/crashpad/tools/crashpad_database_util.cc b/third_party/crashpad/crashpad/tools/crashpad_database_util.cc index cc21698..b4c2a15b 100644 --- a/third_party/crashpad/crashpad/tools/crashpad_database_util.cc +++ b/third_party/crashpad/crashpad/tools/crashpad_database_util.cc
@@ -584,16 +584,13 @@ file_reader = std::move(file_path_reader); } - CrashReportDatabase::NewReport* new_report; + std::unique_ptr<CrashReportDatabase::NewReport> new_report; CrashReportDatabase::OperationStatus status = database->PrepareNewCrashReport(&new_report); if (status != CrashReportDatabase::kNoError) { return EXIT_FAILURE; } - CrashReportDatabase::CallErrorWritingCrashReport - call_error_writing_crash_report(database.get(), new_report); - char buf[4096]; FileOperationResult read_result; do { @@ -601,16 +598,13 @@ if (read_result < 0) { return EXIT_FAILURE; } - if (read_result > 0 && - !LoggingWriteFile(new_report->handle, buf, read_result)) { + if (read_result > 0 && !new_report->Writer()->Write(buf, read_result)) { return EXIT_FAILURE; } } while (read_result > 0); - call_error_writing_crash_report.Disarm(); - UUID uuid; - status = database->FinishedWritingCrashReport(new_report, &uuid); + status = database->FinishedWritingCrashReport(std::move(new_report), &uuid); if (status != CrashReportDatabase::kNoError) { return EXIT_FAILURE; }
diff --git a/third_party/crashpad/crashpad/tools/generate_dump.cc b/third_party/crashpad/crashpad/tools/generate_dump.cc index a470bfd..c1fbde8 100644 --- a/third_party/crashpad/crashpad/tools/generate_dump.cc +++ b/third_party/crashpad/crashpad/tools/generate_dump.cc
@@ -47,6 +47,8 @@ #include "util/win/xp_compat.h" #elif defined(OS_FUCHSIA) #include "snapshot/fuchsia/process_snapshot_fuchsia.h" +#elif defined(OS_LINUX) +#include "snapshot/linux/process_snapshot_linux.h" #endif // OS_MACOSX namespace crashpad { @@ -199,6 +201,12 @@ if (!process_snapshot.Initialize(ZX_HANDLE_INVALID)) { return EXIT_FAILURE; } +#elif defined(OS_LINUX) + // TODO(jperaza): https://crashpad.chromium.org/bug/30. + ProcessSnapshotLinux process_snapshot; + if (!process_snapshot.Initialize(nullptr)) { + return EXIT_FAILURE; + } #endif // OS_MACOSX FileWriter file_writer;
diff --git a/third_party/crashpad/crashpad/util/BUILD.gn b/third_party/crashpad/crashpad/util/BUILD.gn index 13a5da8..4c90785f 100644 --- a/third_party/crashpad/crashpad/util/BUILD.gn +++ b/third_party/crashpad/crashpad/util/BUILD.gn
@@ -14,6 +14,13 @@ import("../build/crashpad_buildconfig.gni") +declare_args() { + if (crashpad_is_linux) { + # Whether the libcurl-based HTTPTransport implementation should be built. + enable_http_transport_libcurl = true + } +} + if (crashpad_is_mac) { if (crashpad_is_in_chromium) { import("//build/config/sysroot.gni") @@ -83,7 +90,9 @@ "misc/address_types.h", "misc/arraysize_unsafe.h", "misc/as_underlying_type.h", + "misc/capture_context.h", "misc/clock.h", + "misc/elf_note_types.h", "misc/from_pointer_cast.h", "misc/implicit_cast.h", "misc/initialization_state.h", @@ -142,6 +151,7 @@ "string/split_string.cc", "string/split_string.h", "synchronization/semaphore.h", + "thread/stoppable.h", "thread/thread.cc", "thread/thread.h", "thread/thread_log_messages.cc", @@ -231,6 +241,7 @@ "mach/task_for_pid.h", "mach/task_memory.cc", "mach/task_memory.h", + "misc/capture_context_mac.S", "misc/clock_mac.cc", "misc/paths_mac.cc", "net/http_transport_mac.mm", @@ -241,7 +252,11 @@ } if (crashpad_is_linux) { - sources += [ "net/http_transport_libcurl.cc" ] + if (enable_http_transport_libcurl) { + sources += [ "net/http_transport_libcurl.cc" ] + } else { + sources += [ "net/http_transport_none.cc" ] + } } if (crashpad_is_linux || crashpad_is_android) { @@ -267,11 +282,14 @@ "linux/ptrace_connection.h", "linux/ptracer.cc", "linux/ptracer.h", + "linux/scoped_pr_set_ptracer.cc", + "linux/scoped_pr_set_ptracer.h", "linux/scoped_ptrace_attach.cc", "linux/scoped_ptrace_attach.h", "linux/thread_info.cc", "linux/thread_info.h", "linux/traits.h", + "misc/capture_context_linux.S", "misc/paths_linux.cc", "posix/process_info_linux.cc", "process/process_memory_linux.cc", @@ -303,7 +321,6 @@ "synchronization/semaphore_win.cc", "thread/thread_win.cc", "win/address_types.h", - "win/capture_context.h", "win/checked_win_address_range.h", "win/command_line.cc", "win/command_line.h", @@ -357,12 +374,12 @@ # https://crbug.com/762167. if (host_os == "win") { sources += [ - "win/capture_context.asm", + "misc/capture_context_win.asm", "win/safe_terminate_process.asm", ] } else { sources += [ - "win/capture_context_broken.cc", + "misc/capture_context_broken.cc", "win/safe_terminate_process_broken.cc", ] } @@ -371,7 +388,7 @@ if (crashpad_is_fuchsia) { sources += [ "misc/paths_fuchsia.cc", - "net/http_transport_fuchsia.cc", + "net/http_transport_none.cc", "process/process_memory_fuchsia.cc", "process/process_memory_fuchsia.h", ] @@ -402,16 +419,22 @@ include_dirs += [ "$root_build_dir/gen" ] } - if (crashpad_is_linux) { + if (crashpad_is_linux && enable_http_transport_libcurl) { libs = [ "curl" ] } if (crashpad_is_win) { - cflags = [ - "/wd4201", # nonstandard extension used : nameless struct/union. - "/wd4577", # 'noexcept' used with no exception handling mode specified. + libs = [ + "user32.lib", + + # TODO(jperaza): version.lib is needed for Windows 7 compatibility. + # mincore.lib may be linked against instead when targeting Windows 8+. + "version.lib", + + "winhttp.lib", ] - libs = [ "winhttp.lib" ] + + cflags = [ "/wd4201" ] # nonstandard extension used: nameless struct/union. if (current_cpu == "x86") { asmflags = [ "/safeseh" ] @@ -430,6 +453,7 @@ "file/filesystem_test.cc", "file/string_file_test.cc", "misc/arraysize_unsafe_test.cc", + "misc/capture_context_test_util.h", "misc/clock_test.cc", "misc/from_pointer_cast_test.cc", "misc/initialization_state_dcheck_test.cc", @@ -463,7 +487,16 @@ "thread/worker_thread_test.cc", ] - if (!crashpad_is_android && !crashpad_is_fuchsia) { + if (!crashpad_is_fuchsia) { + sources += [ + # No NativeCPUContext defined for Fuchsia yet. + # https://crashpad.chromium.org/bug/196. + "misc/capture_context_test.cc", + ] + } + + if (!crashpad_is_android && !crashpad_is_fuchsia && + (!crashpad_is_linux || enable_http_transport_libcurl)) { # Android and Fuchsia will each require an HTTPTransport implementation # (libcurl isn’t in either’s SDK) and a solution to # http_transport_test_server.py, because Python isn’t available on either. @@ -471,8 +504,10 @@ # the build host with a method to forward requests from the device to the # host. # - # TODO(scottmg): Fuchsia will also require an implementation of - # MultiprocessExec for testing. + # Linux optionally compiles in a libcurl-based HTTPTransport, but since curl + # isn't in a base Debian sysroot (which is what Chromium builds against), + # maintain an option to exclude that, for now. + # https://crashpad.chromium.org/bug/220. sources += [ "net/http_transport_test.cc" ] } @@ -508,6 +543,7 @@ "mach/scoped_task_suspend_test.cc", "mach/symbolic_constants_mach_test.cc", "mach/task_memory_test.cc", + "misc/capture_context_test_util_mac.cc", ] } @@ -519,6 +555,7 @@ "linux/ptrace_broker_test.cc", "linux/ptracer_test.cc", "linux/scoped_ptrace_attach_test.cc", + "misc/capture_context_test_util_linux.cc", ] } @@ -532,7 +569,7 @@ if (crashpad_is_win) { sources += [ - "win/capture_context_test.cc", + "misc/capture_context_test_util_win.cc", "win/command_line_test.cc", "win/critical_section_with_debug_info_test.cc", "win/exception_handler_server_test.cc", @@ -568,7 +605,10 @@ } if (crashpad_is_win) { - libs = [ "rpcrt4.lib" ] + libs = [ + "rpcrt4.lib", + "dbghelp.lib", + ] data_deps = [ ":crashpad_util_test_process_info_test_child", ":crashpad_util_test_safe_terminate_process_test_child",
diff --git a/third_party/crashpad/crashpad/util/file/file_io.h b/third_party/crashpad/crashpad/util/file/file_io.h index 044a0a6..050c074 100644 --- a/third_party/crashpad/crashpad/util/file/file_io.h +++ b/third_party/crashpad/crashpad/util/file/file_io.h
@@ -404,6 +404,11 @@ FileWriteMode mode, FilePermissions permissions); +// Fuchsia does not currently support any sort of file locking. See +// https://crashpad.chromium.org/bug/196 and +// https://crashpad.chromium.org/bug/217. +#if !defined(OS_FUCHSIA) + //! \brief Locks the given \a file using `flock()` on POSIX or `LockFileEx()` on //! Windows. //! @@ -433,6 +438,8 @@ //! \return `true` on success, or `false` and a message will be logged. bool LoggingUnlockFile(FileHandle file); +#endif // !OS_FUCHSIA + //! \brief Wraps `lseek()` or `SetFilePointerEx()`. Logs an error if the //! operation fails. //!
diff --git a/third_party/crashpad/crashpad/util/file/file_io_posix.cc b/third_party/crashpad/crashpad/util/file/file_io_posix.cc index 2993279..f311616 100644 --- a/third_party/crashpad/crashpad/util/file/file_io_posix.cc +++ b/third_party/crashpad/crashpad/util/file/file_io_posix.cc
@@ -157,6 +157,8 @@ return fd; } +#if !defined(OS_FUCHSIA) + bool LoggingLockFile(FileHandle file, FileLocking locking) { int operation = (locking == FileLocking::kShared) ? LOCK_SH : LOCK_EX; int rv = HANDLE_EINTR(flock(file, operation)); @@ -170,6 +172,8 @@ return rv == 0; } +#endif // !OS_FUCHSIA + FileOffset LoggingSeekFile(FileHandle file, FileOffset offset, int whence) { off_t rv = lseek(file, offset, whence); PLOG_IF(ERROR, rv < 0) << "lseek";
diff --git a/third_party/crashpad/crashpad/util/file/file_io_test.cc b/third_party/crashpad/crashpad/util/file/file_io_test.cc index fdcf7e9..4446c320 100644 --- a/third_party/crashpad/crashpad/util/file/file_io_test.cc +++ b/third_party/crashpad/crashpad/util/file/file_io_test.cc
@@ -523,6 +523,11 @@ FileShareModeTest(ReadOrWrite::kWrite, ReadOrWrite::kWrite); } +// Fuchsia does not currently support any sort of file locking. See +// https://crashpad.chromium.org/bug/196 and +// https://crashpad.chromium.org/bug/217. +#if !defined(OS_FUCHSIA) + TEST(FileIO, MultipleSharedLocks) { ScopedTempDir temp_dir; base::FilePath shared_file = @@ -648,6 +653,8 @@ LockingTest(FileLocking::kShared, FileLocking::kExclusive); } +#endif // !OS_FUCHSIA + TEST(FileIO, FileSizeByHandle) { EXPECT_EQ(LoggingFileSizeByHandle(kInvalidFileHandle), -1);
diff --git a/third_party/crashpad/crashpad/util/file/filesystem_posix.cc b/third_party/crashpad/crashpad/util/file/filesystem_posix.cc index b1f19f6..c2234da 100644 --- a/third_party/crashpad/crashpad/util/file/filesystem_posix.cc +++ b/third_party/crashpad/crashpad/util/file/filesystem_posix.cc
@@ -65,6 +65,14 @@ bool MoveFileOrDirectory(const base::FilePath& source, const base::FilePath& dest) { +#if defined(OS_FUCHSIA) + // Fuchsia fails and sets errno to EINVAL if source and dest are the same. + // Upstream bug is ZX-1729. + if (!source.empty() && source == dest) { + return true; + } +#endif // OS_FUCHSIA + if (rename(source.value().c_str(), dest.value().c_str()) != 0) { PLOG(ERROR) << "rename " << source.value().c_str() << ", " << dest.value().c_str();
diff --git a/third_party/crashpad/crashpad/util/linux/ptracer.cc b/third_party/crashpad/crashpad/util/linux/ptracer.cc index 2011581..84447362 100644 --- a/third_party/crashpad/crashpad/util/linux/ptracer.cc +++ b/third_party/crashpad/crashpad/util/linux/ptracer.cc
@@ -285,9 +285,9 @@ switch (errno) { #if defined(ARCH_CPU_ARMEL) case EIO: - if (GetGeneralPurposeRegistersLegacy(tid, context, can_log)) { - return sizeof(context->t32); - } + return GetGeneralPurposeRegistersLegacy(tid, context, can_log) + ? sizeof(context->t32) + : 0; #endif // ARCH_CPU_ARMEL default: PLOG_IF(ERROR, can_log) << "ptrace";
diff --git a/third_party/crashpad/crashpad/test/linux/scoped_pr_set_ptracer.cc b/third_party/crashpad/crashpad/util/linux/scoped_pr_set_ptracer.cc similarity index 70% rename from third_party/crashpad/crashpad/test/linux/scoped_pr_set_ptracer.cc rename to third_party/crashpad/crashpad/util/linux/scoped_pr_set_ptracer.cc index bc9695ae..c7aeefc 100644 --- a/third_party/crashpad/crashpad/test/linux/scoped_pr_set_ptracer.cc +++ b/third_party/crashpad/crashpad/util/linux/scoped_pr_set_ptracer.cc
@@ -12,29 +12,26 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "test/linux/scoped_pr_set_ptracer.h" +#include "util/linux/scoped_pr_set_ptracer.h" #include <errno.h> #include <sys/prctl.h> -#include "gtest/gtest.h" -#include "test/errors.h" +#include "base/logging.h" namespace crashpad { -namespace test { -ScopedPrSetPtracer::ScopedPrSetPtracer(pid_t pid) { +ScopedPrSetPtracer::ScopedPrSetPtracer(pid_t pid, bool may_log) + : success_(false), may_log_(may_log) { success_ = prctl(PR_SET_PTRACER, pid, 0, 0, 0) == 0; - if (!success_) { - EXPECT_EQ(errno, EINVAL) << ErrnoMessage("prctl"); - } + PLOG_IF(ERROR, !success_ && may_log && errno != EINVAL) << "prctl"; } ScopedPrSetPtracer::~ScopedPrSetPtracer() { if (success_) { - EXPECT_EQ(prctl(PR_SET_PTRACER, 0, 0, 0, 0), 0) << ErrnoMessage("prctl"); + int res = prctl(PR_SET_PTRACER, 0, 0, 0, 0); + PLOG_IF(ERROR, res != 0 && may_log_) << "prctl"; } } -} // namespace test } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/test/linux/scoped_pr_set_ptracer.h b/third_party/crashpad/crashpad/util/linux/scoped_pr_set_ptracer.h similarity index 69% rename from third_party/crashpad/crashpad/test/linux/scoped_pr_set_ptracer.h rename to third_party/crashpad/crashpad/util/linux/scoped_pr_set_ptracer.h index df9cff7..2bc8677 100644 --- a/third_party/crashpad/crashpad/test/linux/scoped_pr_set_ptracer.h +++ b/third_party/crashpad/crashpad/util/linux/scoped_pr_set_ptracer.h
@@ -12,36 +12,40 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef CRASHPAD_TEST_LINUX_SCOPED_PR_SET_PTRACER_H_ -#define CRASHPAD_TEST_LINUX_SCOPED_PR_SET_PTRACER_H_ +#ifndef CRASHPAD_UTIL_LINUX_SCOPED_PR_SET_PTRACER_H_ +#define CRASHPAD_UTIL_LINUX_SCOPED_PR_SET_PTRACER_H_ #include <sys/types.h> #include "base/macros.h" namespace crashpad { -namespace test { class ScopedPrSetPtracer { public: - //! \brief Uses `PR_SET_PTRACER` to set \a pid as the caller's ptracer or - //! expects `EINVAL`. + //! \brief Uses `PR_SET_PTRACER` to set \a pid as the caller's ptracer. //! //! `PR_SET_PTRACER` is only supported if the Yama Linux security module (LSM) //! is enabled. Otherwise, `prctl(PR_SET_PTRACER, ...)` fails with `EINVAL`. //! See linux-4.9.20/security/yama/yama_lsm.c yama_task_prctl() and //! linux-4.9.20/kernel/sys.c [sys_]prctl(). - explicit ScopedPrSetPtracer(pid_t pid); + //! + //! An error message will be logged on failure only if \a may_log is `true` + //! and `prctl` does not fail with `EINVAL`; + //! + //! \param[in] pid The process ID of the process to make the caller's ptracer. + //! \param[in] may_log if `true`, this class may log error messages. + ScopedPrSetPtracer(pid_t pid, bool may_log); ~ScopedPrSetPtracer(); private: bool success_; + bool may_log_; DISALLOW_COPY_AND_ASSIGN(ScopedPrSetPtracer); }; -} // namespace test } // namespace crashpad -#endif // CRASHPAD_TEST_LINUX_SCOPED_PR_SET_PTRACER_H_ +#endif // CRASHPAD_UTIL_LINUX_SCOPED_PR_SET_PTRACER_H_
diff --git a/third_party/crashpad/crashpad/util/linux/scoped_ptrace_attach_test.cc b/third_party/crashpad/crashpad/util/linux/scoped_ptrace_attach_test.cc index 78552e77..d009e682 100644 --- a/third_party/crashpad/crashpad/util/linux/scoped_ptrace_attach_test.cc +++ b/third_party/crashpad/crashpad/util/linux/scoped_ptrace_attach_test.cc
@@ -20,9 +20,9 @@ #include "gtest/gtest.h" #include "test/errors.h" -#include "test/linux/scoped_pr_set_ptracer.h" #include "test/multiprocess.h" #include "util/file/file_io.h" +#include "util/linux/scoped_pr_set_ptracer.h" namespace crashpad { namespace test { @@ -75,7 +75,7 @@ } void MultiprocessChild() override { - ScopedPrSetPtracer set_ptracer(getppid()); + ScopedPrSetPtracer set_ptracer(getppid(), /* may_log= */ true); char c = '\0'; CheckedWriteFile(WritePipeHandle(), &c, sizeof(c)); @@ -98,7 +98,7 @@ private: void MultiprocessParent() override { - ScopedPrSetPtracer set_ptracer(ChildPID()); + ScopedPrSetPtracer set_ptracer(ChildPID(), /* may_log= */ true); char c = '\0'; CheckedWriteFile(WritePipeHandle(), &c, sizeof(c)); @@ -140,7 +140,7 @@ private: void MultiprocessParent() override { - ScopedPrSetPtracer set_ptracer(ChildPID()); + ScopedPrSetPtracer set_ptracer(ChildPID(), /* may_log= */ true); char c = '\0'; CheckedWriteFile(WritePipeHandle(), &c, sizeof(c));
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context.h b/third_party/crashpad/crashpad/util/misc/capture_context.h new file mode 100644 index 0000000..5c1838a --- /dev/null +++ b/third_party/crashpad/crashpad/util/misc/capture_context.h
@@ -0,0 +1,87 @@ +// Copyright 2014 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_UTIL_MISC_CAPTURE_CONTEXT_H_ +#define CRASHPAD_UTIL_MISC_CAPTURE_CONTEXT_H_ + +#include "build/build_config.h" + +#if defined(OS_MACOSX) +#include <mach/mach.h> +#elif defined(OS_WIN) +#include <windows.h> +#elif defined(OS_LINUX) || defined(OS_ANDROID) +#include <ucontext.h> +#endif // OS_MACOSX + +namespace crashpad { + +#if defined(OS_MACOSX) +#if defined(ARCH_CPU_X86_FAMILY) +using NativeCPUContext = x86_thread_state; +#endif +#elif defined(OS_WIN) +using NativeCPUContext = CONTEXT; +#elif defined(OS_LINUX) || defined(OS_ANDROID) +using NativeCPUContext = ucontext_t; +#endif // OS_MACOSX + +// No NativeCPUContext defined for Fuchsia yet. +// https://crashpad.chromium.org/bug/196. +#if !defined(OS_FUCHSIA) + +//! \brief Saves the CPU context. +//! +//! The CPU context will be captured as accurately and completely as possible, +//! containing an atomic snapshot at the point of this function’s return. This +//! function does not modify any registers. +//! +//! This function is a replacement for `RtlCaptureContext()` and `getcontext()` +//! which contain bugs and/or limitations. +//! +//! On 32-bit x86, `RtlCaptureContext()` requires that `ebp` be used as a frame +//! pointer, and returns `ebp`, `esp`, and `eip` out of sync with the other +//! registers. Both the 32-bit x86 and 64-bit x86_64 versions of +//! `RtlCaptureContext()` capture only the state of the integer registers, +//! ignoring floating-point and vector state. +//! +//! \param[out] cpu_context The structure to store the context in. +//! +//! \note The ABI may require that this function's argument is passed by +//! register, preventing this fuction from saving the original value of that +//! register. This occurs in the following circumstances: +//! +//! OS | Architecture | Register +//! ------------|--------------|--------- +//! Win | x86_64 | `%%rcx` +//! macOS/Linux | x86_64 | `%%rdi` +//! Linux | ARM/ARM64 | `r0`/`x0` +//! +//! Additionally, the value `LR` on ARM/ARM64 will be the return address of +//! this function. +//! +//! If the value of these register prior to calling this function are needed +//! they must be obtained separately prior to calling this function. For +//! example: +//! \code +//! uint64_t rdi; +//! asm("movq %%rdi, %0" : "=m"(rdi)); +//! \endcode +void CaptureContext(NativeCPUContext* cpu_context); + +#endif // !OS_FUCHSIA + +} // namespace crashpad + +#endif // CRASHPAD_UTIL_MISC_CAPTURE_CONTEXT_H_
diff --git a/third_party/crashpad/crashpad/util/win/capture_context_broken.cc b/third_party/crashpad/crashpad/util/misc/capture_context_broken.cc similarity index 90% rename from third_party/crashpad/crashpad/util/win/capture_context_broken.cc rename to third_party/crashpad/crashpad/util/misc/capture_context_broken.cc index 4a641515..ab7a5974 100644 --- a/third_party/crashpad/crashpad/util/win/capture_context_broken.cc +++ b/third_party/crashpad/crashpad/util/misc/capture_context_broken.cc
@@ -12,13 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "util/win/capture_context.h" +#include "util/misc/capture_context.h" #include "base/logging.h" namespace crashpad { -void CaptureContext(CONTEXT* context) { +void CaptureContext(NativeCPUContext* context) { // Don't use this file in production. CHECK(false) << "Don't use this! For cross builds only. See https://crbug.com/762167.";
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_linux.S b/third_party/crashpad/crashpad/util/misc/capture_context_linux.S new file mode 100644 index 0000000..c16d0c7 --- /dev/null +++ b/third_party/crashpad/crashpad/util/misc/capture_context_linux.S
@@ -0,0 +1,324 @@ +// Copyright 2018 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. + +// namespace crashpad { +// void CaptureContext(ucontext_t* context); +// } // namespace crashpad +#define CAPTURECONTEXT_SYMBOL _ZN8crashpad14CaptureContextEP8ucontext + + .text + .globl CAPTURECONTEXT_SYMBOL +#if defined(__i386__) || defined(__x86_64__) + .balign 16, 0x90 +#elif defined(__arm__) || defined(__aarch64__) + .balign 4, 0x0 +#endif + +CAPTURECONTEXT_SYMBOL: + +#if defined(__i386__) + + .cfi_startproc + + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset %ebp, -8 + movl %esp, %ebp + .cfi_def_cfa_register %ebp + + // Note that 16-byte stack alignment is not maintained because this function + // does not call out to any other. + + // pushfl first, because some instructions (but probably none used here) + // affect %eflags. %eflags will be in -4(%ebp). + pushfl + + // Save the original value of %eax, and use %eax to hold the ucontext_t* + // argument. The original value of %eax will be in -8(%ebp). + pushl %eax + movl 8(%ebp), %eax + + // Save the original value of %ecx, and use %ecx as a scratch register. + pushl %ecx + + // The segment registers are 16 bits wide, but mcontext_t declares them + // as unsigned 32-bit values, so zero the top half. + xorl %ecx, %ecx + movw %gs, %cx + movl %ecx, 0x14(%eax) // context->uc_mcontext.xgs + movw %fs, %cx + movl %ecx, 0x18(%eax) // context->uc_mcontext.xfs + movw %es, %cx + movl %ecx, 0x1c(%eax) // context->uc_mcontext.xes + movw %ds, %cx + movl %ecx, 0x20(%eax) // context->uc_mcontext.xds + + // General-purpose registers whose values haven’t changed can be captured + // directly. + movl %edi, 0x24(%eax) // context->uc_mcontext.edi + movl %esi, 0x28(%eax) // context->uc_mcontext.esi + + // The original %ebp was saved on the stack in this function’s prologue. + movl (%ebp), %ecx + movl %ecx, 0x2c(%eax) // context->uc_mcontext.ebp + + // %esp was saved in %ebp in this function’s prologue, but the caller’s %esp + // is 8 more than this value: 4 for the original %ebp saved on the stack in + // this function’s prologue, and 4 for the return address saved on the stack + // by the call instruction that reached this function. + leal 8(%ebp), %ecx + movl %ecx, 0x30(%eax) // context->uc_mcontext.esp + + // More general-purpose registers + movl %ebx, 0x34(%eax) // context->uc_mcontext.ebx + movl %edx, 0x38(%eax) // context->uc_mcontext.edx + + // The original %ecx was saved on the stack above. + movl -12(%ebp), %ecx + movl %ecx, 0x3c(%eax) // context->uc_mcontext.ecx + + // The original %eax was saved on the stack above. + movl -8(%ebp), %ecx + movl %ecx, 0x40(%eax) // context->uc_mcontext.eax + + // trapno and err are unused so zero them out. + xorl %ecx, %ecx + movl %ecx, 0x44(%eax) // context->uc_mcontext.trapno + movl %ecx, 0x48(%eax) // context->uc_mcontext.err + + // %eip can’t be accessed directly, but the return address saved on the stack + // by the call instruction that reached this function can be used. + movl 4(%ebp), %ecx + movl %ecx, 0x4c(%eax) // context->uc_mcontext.eip + + // More segment registers + xorl %ecx, %ecx + movw %cs, %cx + movl %ecx, 0x50(%eax) // context->uc_mcontext.xcs + + // The original %eflags was saved on the stack above. + movl -4(%ebp), %ecx + movl %ecx, 0x54(%eax) // context->uc_mcontext.eflags + + // uesp is unused so zero it out. + xorl %ecx, %ecx + movl %ecx, 0x58(%eax) // context->uc_mcontext.uesp + + // The last segment register. + movw %ss, %cx + movl %ecx, 0x5c(%eax) // context->uc_mcontext.xss + + // TODO(jperaza): save floating-point registers. + + // Clean up by restoring clobbered registers, even those considered volatile + // by the ABI, so that the captured context represents the state at this + // function’s exit. + popl %ecx + popl %eax + popfl + + popl %ebp + + ret + + .cfi_endproc + +#elif defined(__x86_64__) + + .cfi_startproc + + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + + // Note that 16-byte stack alignment is not maintained because this function + // does not call out to any other. + + // pushfq first, because some instructions (but probably none used here) + // affect %rflags. %rflags will be in -8(%rbp). + pushfq + + // General-purpose registers whose values haven’t changed can be captured + // directly. + movq %r8, 0x28(%rdi) // context->uc_mcontext.r8 + movq %r9, 0x30(%rdi) // context->uc_mcontext.r9 + movq %r10, 0x38(%rdi) // context->uc_mcontext.r10 + movq %r11, 0x40(%rdi) // context->uc_mcontext.r11 + movq %r12, 0x48(%rdi) // context->uc_mcontext.r12 + movq %r13, 0x50(%rdi) // context->uc_mcontext.r13 + movq %r14, 0x58(%rdi) // context->uc_mcontext.r14 + movq %r15, 0x60(%rdi) // context->uc_mcontext.r15 + + // Because of the calling convention, there’s no way to recover the value of + // the caller’s %rdi as it existed prior to calling this function. This + // function captures a snapshot of the register state at its return, which + // involves %rdi containing a pointer to its first argument. Callers that + // require the value of %rdi prior to calling this function should obtain it + // separately. For example: + // uint64_t rdi; + // asm("movq %%rdi, %0" : "=m"(rdi)); + movq %rdi, 0x68(%rdi) // context->uc_mcontext.rdi + + movq %rsi, 0x70(%rdi) // context->uc_mcontext.rsi + + // Use %r8 as a scratch register now that it has been saved. + // The original %rbp was saved on the stack in this function’s prologue. + movq (%rbp), %r8 + movq %r8, 0x78(%rdi) // context->uc_mcontext.rbp + + // Save the remaining general-purpose registers. + movq %rbx, 0x80(%rdi) // context->uc_mcontext.rbx + movq %rdx, 0x88(%rdi) // context->uc_mcontext.rdx + movq %rax, 0x90(%rdi) // context->uc_mcontext.rax + movq %rcx, 0x98(%rdi) // context->uc_mcontext.rcx + + // %rsp was saved in %rbp in this function’s prologue, but the caller’s %rsp + // is 16 more than this value: 8 for the original %rbp saved on the stack in + // this function’s prologue, and 8 for the return address saved on the stack + // by the call instruction that reached this function. + leaq 16(%rbp), %r8 + movq %r8, 0xa0(%rdi) // context->uc_mcontext.rsp + + // %rip can’t be accessed directly, but the return address saved on the stack + // by the call instruction that reached this function can be used. + movq 8(%rbp), %r8 + movq %r8, 0xa8(%rdi) // context->uc_mcontext.rip + + // The original %rflags was saved on the stack above. + movq -8(%rbp), %r8 + movq %r8, 0xb0(%rdi) // context->uc_mcontext.eflags + + // Save the segment registers + movw %cs, 0xb8(%rdi) // context->uc_mcontext.cs + movw %gs, 0xba(%rdi) // context->uc_mcontext.gs + movw %fs, 0xbc(%rdi) // context->uc_mcontext.fs + + xorw %ax, %ax + movw %ax, 0xbe(%rdi) // context->uc_mcontext.padding + + // Zero out the remainder of the unused pseudo-registers + xorq %r8, %r8 + movq %r8, 0xc0(%rdi) // context->uc_mcontext.err + movq %r8, 0xc8(%rdi) // context->uc_mcontext.trapno + movq %r8, 0xd0(%rdi) // context->uc_mcontext.oldmask + movq %r8, 0xd8(%rdi) // context->uc_mcontext.cr2 + + // Clean up by restoring clobbered registers, even those considered volatile + // by the ABI, so that the captured context represents the state at this + // function’s exit. + movq 0x90(%rdi), %rax + movq 0x28(%rdi), %r8 + + // TODO(jperaza): save floating-point registers. + + popfq + + popq %rbp + + ret + + .cfi_endproc + +#elif defined(__arm__) + + // The original r0 can't be recovered. + str r0, [r0, #0x20] + + // Now advance r0 to point to the register array. + add r0, r0, #0x24 + + // Save registers r1-r12 at context->uc_mcontext.regs[i]. + stm r0, {r1-r12} + + // Restore r0. + sub r0, r0, #0x24 + + // Save named general purpose registers. + str FP, [r0, #0x4c] // context->uc_mcontext.fp + str IP, [r0, #0x50] // context->uc_mcontext.ip + str SP, [r0, #0x54] // context->uc_mcontext.sp + + // The original LR can't be recovered. + str LR, [r0, #0x58] // context->uc_mcontext.lr + + // The link register holds the return address for this function. + str LR, [r0, #0x5c] // context->uc_mcontext.pc + + // Use r1 as a scratch register. + + // CPSR is a deprecated synonym for APSR. + mrs r1, APSR + str r1, [r0, #0x60] // context->uc_mcontext.cpsr + + // Zero out unused fields. + mov r1, #0x0 + str r1, [r0, #0x14] // context->uc_mcontext.trap_no + str r1, [r0, #0x18] // context->uc_mcontext.error_code + str r1, [r0, #0x1c] // context->uc_mcontext.oldmask + str r1, [r0, #0x64] // context->uc_mcontext.fault_address + + // Restore r1. + ldr r1, [r0, #0x24] + + // TODO(jperaza): save floating-point registers. + + mov PC, LR + +#elif defined(__aarch64__) + + // Zero out fault_address, which is unused. + str x31, [x0, #0xb0] // context->uc_mcontext.fault_address + + // Save general purpose registers in context->uc_mcontext.regs[i]. + // The original x0 can't be recovered. + stp x0, x1, [x0, #0xb8] + stp x2, x3, [x0, #0xc8] + stp x4, x5, [x0, #0xd8] + stp x6, x7, [x0, #0xe8] + stp x8, x9, [x0, #0xf8] + stp x10, x11, [x0, #0x108] + stp x12, x13, [x0, #0x118] + stp x14, x15, [x0, #0x128] + stp x16, x17, [x0, #0x138] + stp x18, x19, [x0, #0x148] + stp x20, x21, [x0, #0x158] + stp x22, x23, [x0, #0x168] + stp x24, x25, [x0, #0x178] + stp x26, x27, [x0, #0x188] + stp x28, x29, [x0, #0x198] + + // The original LR can't be recovered. + str LR, [x0, #0x1a8] + + // Use x1 as a scratch register. + mov x1, SP + str x1, [x0, #0x1b0] // context->uc_mcontext.sp + + // The link register holds the return address for this function. + str LR, [x0, #0x1b8] // context->uc_mcontext.pc + + // NZCV, pstate, and CPSR are synonyms. + mrs x1, NZCV + str x1, [x0, #0x1c0] // context->uc_mcontext.pstate + + // Restore x1 from the saved context. + ldr x1, [x0, #0xc0] + + // TODO(jperaza): save floating-point registers. + + ret + +#endif // __i386__
diff --git a/third_party/crashpad/crashpad/client/capture_context_mac.S b/third_party/crashpad/crashpad/util/misc/capture_context_mac.S similarity index 99% rename from third_party/crashpad/crashpad/client/capture_context_mac.S rename to third_party/crashpad/crashpad/util/misc/capture_context_mac.S index 942d841..39c6ca6a 100644 --- a/third_party/crashpad/crashpad/client/capture_context_mac.S +++ b/third_party/crashpad/crashpad/util/misc/capture_context_mac.S
@@ -22,7 +22,7 @@ .section __TEXT,__text,regular,pure_instructions .private_extern CAPTURECONTEXT_SYMBOL .globl CAPTURECONTEXT_SYMBOL - .align 4, 0x90 + .balign 16, 0x90 CAPTURECONTEXT_SYMBOL: #if defined(__i386__)
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_test.cc b/third_party/crashpad/crashpad/util/misc/capture_context_test.cc new file mode 100644 index 0000000..e31883e7 --- /dev/null +++ b/third_party/crashpad/crashpad/util/misc/capture_context_test.cc
@@ -0,0 +1,95 @@ +// Copyright 2014 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 "util/misc/capture_context.h" + +#include <stdint.h> + +#include <algorithm> + +#include "gtest/gtest.h" +#include "util/misc/address_sanitizer.h" +#include "util/misc/capture_context_test_util.h" + +namespace crashpad { +namespace test { +namespace { + +void TestCaptureContext() { + NativeCPUContext context_1; + CaptureContext(&context_1); + + { + SCOPED_TRACE("context_1"); + ASSERT_NO_FATAL_FAILURE(SanityCheckContext(context_1)); + } + + // The program counter reference value is this function’s address. The + // captured program counter should be slightly greater than or equal to the + // reference program counter. + uintptr_t pc = ProgramCounterFromContext(context_1); + +#if !defined(ADDRESS_SANITIZER) + // AddressSanitizer can cause enough code bloat that the “nearby” check would + // likely fail. + const uintptr_t kReferencePC = + reinterpret_cast<uintptr_t>(TestCaptureContext); + EXPECT_PRED2([](uintptr_t actual, + uintptr_t reference) { return actual - reference < 64u; }, + pc, + kReferencePC); +#endif // !defined(ADDRESS_SANITIZER) + + // Declare sp and context_2 here because all local variables need to be + // declared before computing the stack pointer reference value, so that the + // reference value can be the lowest value possible. + uintptr_t sp; + NativeCPUContext context_2; + + // The stack pointer reference value is the lowest address of a local variable + // in this function. The captured program counter will be slightly less than + // or equal to the reference stack pointer. + const uintptr_t kReferenceSP = + std::min(std::min(reinterpret_cast<uintptr_t>(&context_1), + reinterpret_cast<uintptr_t>(&context_2)), + std::min(reinterpret_cast<uintptr_t>(&pc), + reinterpret_cast<uintptr_t>(&sp))); + sp = StackPointerFromContext(context_1); + EXPECT_PRED2([](uintptr_t actual, + uintptr_t reference) { return reference - actual < 512u; }, + sp, + kReferenceSP); + + // Capture the context again, expecting that the stack pointer stays the same + // and the program counter increases. Strictly speaking, there’s no guarantee + // that these conditions will hold, although they do for known compilers even + // under typical optimization. + CaptureContext(&context_2); + + { + SCOPED_TRACE("context_2"); + ASSERT_NO_FATAL_FAILURE(SanityCheckContext(context_2)); + } + + EXPECT_EQ(StackPointerFromContext(context_2), sp); + EXPECT_GT(ProgramCounterFromContext(context_2), pc); +} + +TEST(CaptureContext, CaptureContext) { + ASSERT_NO_FATAL_FAILURE(TestCaptureContext()); +} + +} // namespace +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_test_util.h b/third_party/crashpad/crashpad/util/misc/capture_context_test_util.h new file mode 100644 index 0000000..5a5ff7d --- /dev/null +++ b/third_party/crashpad/crashpad/util/misc/capture_context_test_util.h
@@ -0,0 +1,41 @@ +// Copyright 2018 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 "util/misc/capture_context.h" + +#include <stdint.h> + +namespace crashpad { +namespace test { + +//! \brief Sanity check conditions that should be true for any NativeCPUContext +//! produced by CaptureContext(). +//! +//! If the context structure has fields that tell whether it’s valid, such as +//! magic numbers or size fields, sanity-checks those fields for validity with +//! fatal gtest assertions. For other fields, where it’s possible to reason +//! about their validity based solely on their contents, sanity-checks via +//! nonfatal gtest assertions. +//! +//! \param[in] context The context to check. +void SanityCheckContext(const NativeCPUContext& context); + +//! \brief Return the value of the program counter from a NativeCPUContext. +uintptr_t ProgramCounterFromContext(const NativeCPUContext& context); + +//! \brief Return the value of the stack pointer from a NativeCPUContext. +uintptr_t StackPointerFromContext(const NativeCPUContext& context); + +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc new file mode 100644 index 0000000..fb64e5d --- /dev/null +++ b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_linux.cc
@@ -0,0 +1,62 @@ +// Copyright 2018 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 "util/misc/capture_context_test_util.h" + +#include "base/logging.h" +#include "gtest/gtest.h" +#include "util/misc/from_pointer_cast.h" + +namespace crashpad { +namespace test { + +void SanityCheckContext(const NativeCPUContext& context) { +#if defined(ARCH_CPU_X86) + // Nothing to do here yet. +#elif defined(ARCH_CPU_X86_64) + EXPECT_EQ(context.uc_mcontext.gregs[REG_RDI], + FromPointerCast<intptr_t>(&context)); +#elif defined(ARCH_CPU_ARMEL) + EXPECT_EQ(context.uc_mcontext.arm_r0, FromPointerCast<uintptr_t>(&context)); +#elif defined(ARCH_CPU_ARM64) + EXPECT_EQ(context.uc_mcontext.regs[0], FromPointerCast<uintptr_t>(&context)); +#endif +} + +uintptr_t ProgramCounterFromContext(const NativeCPUContext& context) { +#if defined(ARCH_CPU_X86) + return context.uc_mcontext.gregs[REG_EIP]; +#elif defined(ARCH_CPU_X86_64) + return context.uc_mcontext.gregs[REG_RIP]; +#elif defined(ARCH_CPU_ARMEL) + return context.uc_mcontext.arm_pc; +#elif defined(ARCH_CPU_ARM64) + return context.uc_mcontext.pc; +#endif +} + +uintptr_t StackPointerFromContext(const NativeCPUContext& context) { +#if defined(ARCH_CPU_X86) + return context.uc_mcontext.gregs[REG_ESP]; +#elif defined(ARCH_CPU_X86_64) + return context.uc_mcontext.gregs[REG_RSP]; +#elif defined(ARCH_CPU_ARMEL) + return context.uc_mcontext.arm_sp; +#elif defined(ARCH_CPU_ARM64) + return context.uc_mcontext.sp; +#endif +} + +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_test_util_mac.cc b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_mac.cc new file mode 100644 index 0000000..afe0916 --- /dev/null +++ b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_mac.cc
@@ -0,0 +1,84 @@ +// Copyright 2018 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 "util/misc/capture_context_test_util.h" + +#include "gtest/gtest.h" +#include "util/misc/implicit_cast.h" + +namespace crashpad { +namespace test { + +void SanityCheckContext(const NativeCPUContext& context) { +#if defined(ARCH_CPU_X86) + ASSERT_EQ(implicit_cast<thread_state_flavor_t>(context.tsh.flavor), + implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE32)); + ASSERT_EQ(implicit_cast<uint32_t>(context.tsh.count), + implicit_cast<uint32_t>(x86_THREAD_STATE32_COUNT)); +#elif defined(ARCH_CPU_X86_64) + ASSERT_EQ(implicit_cast<thread_state_flavor_t>(context.tsh.flavor), + implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE64)); + ASSERT_EQ(implicit_cast<uint32_t>(context.tsh.count), + implicit_cast<uint32_t>(x86_THREAD_STATE64_COUNT)); +#endif + +#if defined(ARCH_CPU_X86_FAMILY) +// The segment registers are only capable of storing 16-bit quantities, but +// the context structure provides native integer-width fields for them. Ensure +// that the high bits are all clear. +// +// Many bit positions in the flags register are reserved and will always read +// a known value. Most reserved bits are always 0, but bit 1 is always 1. +// Check that the reserved bits are all set to their expected values. Note +// that the set of reserved bits may be relaxed over time with newer CPUs, and +// that this test may need to be changed to reflect these developments. The +// current set of reserved bits are 1, 3, 5, 15, and 22 and higher. See Intel +// Software Developer’s Manual, Volume 1: Basic Architecture (253665-051), +// 3.4.3 “EFLAGS Register”, and AMD Architecture Programmer’s Manual, Volume +// 2: System Programming (24593-3.24), 3.1.6 “RFLAGS Register”. +#if defined(ARCH_CPU_X86) + EXPECT_EQ(context.uts.ts32.__cs & ~0xffff, 0u); + EXPECT_EQ(context.uts.ts32.__ds & ~0xffff, 0u); + EXPECT_EQ(context.uts.ts32.__es & ~0xffff, 0u); + EXPECT_EQ(context.uts.ts32.__fs & ~0xffff, 0u); + EXPECT_EQ(context.uts.ts32.__gs & ~0xffff, 0u); + EXPECT_EQ(context.uts.ts32.__ss & ~0xffff, 0u); + EXPECT_EQ(context.uts.ts32.__eflags & 0xffc0802a, 2u); +#elif defined(ARCH_CPU_X86_64) + EXPECT_EQ(context.uts.ts64.__cs & ~UINT64_C(0xffff), 0u); + EXPECT_EQ(context.uts.ts64.__fs & ~UINT64_C(0xffff), 0u); + EXPECT_EQ(context.uts.ts64.__gs & ~UINT64_C(0xffff), 0u); + EXPECT_EQ(context.uts.ts64.__rflags & UINT64_C(0xffffffffffc0802a), 2u); +#endif +#endif +} + +uintptr_t ProgramCounterFromContext(const NativeCPUContext& context) { +#if defined(ARCH_CPU_X86) + return context.uts.ts32.__eip; +#elif defined(ARCH_CPU_X86_64) + return context.uts.ts64.__rip; +#endif +} + +uintptr_t StackPointerFromContext(const NativeCPUContext& context) { +#if defined(ARCH_CPU_X86) + return context.uts.ts32.__esp; +#elif defined(ARCH_CPU_X86_64) + return context.uts.ts64.__rsp; +#endif +} + +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context_test_util_win.cc b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_win.cc new file mode 100644 index 0000000..239beac --- /dev/null +++ b/third_party/crashpad/crashpad/util/misc/capture_context_test_util_win.cc
@@ -0,0 +1,114 @@ +// Copyright 2018 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 "util/misc/capture_context_test_util.h" + +#include "base/macros.h" +#include "gtest/gtest.h" + +namespace crashpad { +namespace test { + +void SanityCheckContext(const NativeCPUContext& context) { +#if defined(ARCH_CPU_X86) + constexpr uint32_t must_have = CONTEXT_i386 | CONTEXT_CONTROL | + CONTEXT_INTEGER | CONTEXT_SEGMENTS | + CONTEXT_FLOATING_POINT; + ASSERT_EQ(context.ContextFlags & must_have, must_have); + constexpr uint32_t may_have = CONTEXT_EXTENDED_REGISTERS; + ASSERT_EQ(context.ContextFlags & ~(must_have | may_have), 0u); +#elif defined(ARCH_CPU_X86_64) + ASSERT_EQ( + context.ContextFlags, + static_cast<DWORD>(CONTEXT_AMD64 | CONTEXT_CONTROL | CONTEXT_INTEGER | + CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT)); +#endif + +#if defined(ARCH_CPU_X86_FAMILY) + // Many bit positions in the flags register are reserved and will always read + // a known value. Most reserved bits are always 0, but bit 1 is always 1. + // Check that the reserved bits are all set to their expected values. Note + // that the set of reserved bits may be relaxed over time with newer CPUs, and + // that this test may need to be changed to reflect these developments. The + // current set of reserved bits are 1, 3, 5, 15, and 22 and higher. See Intel + // Software Developer’s Manual, Volume 1: Basic Architecture (253665-055), + // 3.4.3 “EFLAGS Register”, and AMD Architecture Programmer’s Manual, Volume + // 2: System Programming (24593-3.25), 3.1.6 “RFLAGS Register”. + EXPECT_EQ(context.EFlags & 0xffc0802a, 2u); + + // CaptureContext() doesn’t capture debug registers, so make sure they read 0. + EXPECT_EQ(context.Dr0, 0u); + EXPECT_EQ(context.Dr1, 0u); + EXPECT_EQ(context.Dr2, 0u); + EXPECT_EQ(context.Dr3, 0u); + EXPECT_EQ(context.Dr6, 0u); + EXPECT_EQ(context.Dr7, 0u); +#endif + +#if defined(ARCH_CPU_X86) + // fxsave doesn’t write these bytes. + for (size_t i = 464; i < arraysize(context.ExtendedRegisters); ++i) { + SCOPED_TRACE(i); + EXPECT_EQ(context.ExtendedRegisters[i], 0); + } +#elif defined(ARCH_CPU_X86_64) + // mxcsr shows up twice in the context structure. Make sure the values are + // identical. + EXPECT_EQ(context.FltSave.MxCsr, context.MxCsr); + + // fxsave doesn’t write these bytes. + for (size_t i = 0; i < arraysize(context.FltSave.Reserved4); ++i) { + SCOPED_TRACE(i); + EXPECT_EQ(context.FltSave.Reserved4[i], 0); + } + + // CaptureContext() doesn’t use these fields. + EXPECT_EQ(context.P1Home, 0u); + EXPECT_EQ(context.P2Home, 0u); + EXPECT_EQ(context.P3Home, 0u); + EXPECT_EQ(context.P4Home, 0u); + EXPECT_EQ(context.P5Home, 0u); + EXPECT_EQ(context.P6Home, 0u); + for (size_t i = 0; i < arraysize(context.VectorRegister); ++i) { + SCOPED_TRACE(i); + EXPECT_EQ(context.VectorRegister[i].Low, 0u); + EXPECT_EQ(context.VectorRegister[i].High, 0u); + } + EXPECT_EQ(context.VectorControl, 0u); + EXPECT_EQ(context.DebugControl, 0u); + EXPECT_EQ(context.LastBranchToRip, 0u); + EXPECT_EQ(context.LastBranchFromRip, 0u); + EXPECT_EQ(context.LastExceptionToRip, 0u); + EXPECT_EQ(context.LastExceptionFromRip, 0u); +#endif +} + +uintptr_t ProgramCounterFromContext(const NativeCPUContext& context) { +#if defined(ARCH_CPU_X86) + return context.Eip; +#elif defined(ARCH_CPU_X86_64) + return context.Rip; +#endif +} + +uintptr_t StackPointerFromContext(const NativeCPUContext& context) { +#if defined(ARCH_CPU_X86) + return context.Esp; +#elif defined(ARCH_CPU_X86_64) + return context.Rsp; +#endif +} + +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/win/capture_context.asm b/third_party/crashpad/crashpad/util/misc/capture_context_win.asm similarity index 100% rename from third_party/crashpad/crashpad/util/win/capture_context.asm rename to third_party/crashpad/crashpad/util/misc/capture_context_win.asm
diff --git a/third_party/crashpad/crashpad/util/misc/elf_note_types.h b/third_party/crashpad/crashpad/util/misc/elf_note_types.h new file mode 100644 index 0000000..77c9043 --- /dev/null +++ b/third_party/crashpad/crashpad/util/misc/elf_note_types.h
@@ -0,0 +1,34 @@ +// Copyright 2018 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_UTIL_MISC_ELF_NOTE_TYPES_H_ +#define CRASHPAD_UTIL_MISC_ELF_NOTE_TYPES_H_ + +// This header defines types of ELF "notes" that are embedded sections. These +// can be read by ElfImageReader in the snapshot library, and are created in +// client modules. All notes used by Crashpad use the name "Crashpad" and one of +// the types defined here. Note that this file is #included into .S files, so +// must be relatively plain (no C++ features). + +#define CRASHPAD_ELF_NOTE_NAME "Crashpad" + +// Used by ElfImageReader for testing purposes. +#define CRASHPAD_ELF_NOTE_TYPE_SNAPSHOT_TEST 1 + +// Used by the client library to stash a pointer to the CrashpadInfo structure +// for retrieval by the module snapshot. 'OFNI' == 0x4f464e49 which appears as +// "INFO" in readelf -x. +#define CRASHPAD_ELF_NOTE_TYPE_CRASHPAD_INFO 0x4f464e49 + +#endif // CRASHPAD_UTIL_MISC_ELF_NOTE_TYPES_H_
diff --git a/third_party/crashpad/crashpad/util/misc/metrics.cc b/third_party/crashpad/crashpad/util/misc/metrics.cc index f4fb588..7d191f7 100644 --- a/third_party/crashpad/crashpad/util/misc/metrics.cc +++ b/third_party/crashpad/crashpad/util/misc/metrics.cc
@@ -61,8 +61,7 @@ } // static -void Metrics::CrashReportSize(FileHandle file) { - const FileOffset size = LoggingFileSizeByHandle(file); +void Metrics::CrashReportSize(FileOffset size) { UMA_HISTOGRAM_CUSTOM_COUNTS( "Crashpad.CrashReportSize", size, 0, 20 * 1024 * 1024, 50); }
diff --git a/third_party/crashpad/crashpad/util/misc/metrics.h b/third_party/crashpad/crashpad/util/misc/metrics.h index b4bea910..54ccb84 100644 --- a/third_party/crashpad/crashpad/util/misc/metrics.h +++ b/third_party/crashpad/crashpad/util/misc/metrics.h
@@ -50,7 +50,7 @@ //! \brief Reports the size of a crash report file in bytes. Should be called //! when a new report is written to disk. - static void CrashReportSize(FileHandle file); + static void CrashReportSize(FileOffset size); //! \brief Reports on a crash upload attempt, and if it succeeded. static void CrashUploadAttempted(bool successful); @@ -119,6 +119,16 @@ //! \brief There was a database error in attempt to complete the report. kFinishedWritingCrashReportFailed = 7, + //! \brief An attempt to directly `ptrace` the target failed. + //! + //! This value is only used on Linux/Android. + kDirectPtraceFailed = 8, + + //! \brief An attempt to `ptrace` via a PtraceBroker failed. + //! + //! This value is only used on Linux/Android. + kBrokeredPtraceFailed = 9, + //! \brief The number of values in this enumeration; not a valid value. kMaxValue };
diff --git a/third_party/crashpad/crashpad/util/misc/uuid.cc b/third_party/crashpad/crashpad/util/misc/uuid.cc index 92fba760..ffd49708 100644 --- a/third_party/crashpad/crashpad/util/misc/uuid.cc +++ b/third_party/crashpad/crashpad/util/misc/uuid.cc
@@ -84,6 +84,10 @@ return true; } +bool UUID::InitializeFromString(const base::StringPiece16& string) { + return InitializeFromString(UTF16ToUTF8(string)); +} + bool UUID::InitializeWithNew() { #if defined(OS_MACOSX) uuid_t uuid;
diff --git a/third_party/crashpad/crashpad/util/misc/uuid.h b/third_party/crashpad/crashpad/util/misc/uuid.h index 4e5884e2..af801222 100644 --- a/third_party/crashpad/crashpad/util/misc/uuid.h +++ b/third_party/crashpad/crashpad/util/misc/uuid.h
@@ -63,6 +63,7 @@ //! been initialized with the data. `false` if the string could not be //! parsed, with the object state untouched. bool InitializeFromString(const base::StringPiece& string); + bool InitializeFromString(const base::StringPiece16& string); //! \brief Initializes the %UUID using a standard system facility to generate //! the value.
diff --git a/third_party/crashpad/crashpad/util/misc/uuid_test.cc b/third_party/crashpad/crashpad/util/misc/uuid_test.cc index 72b8216..c05c5c1b 100644 --- a/third_party/crashpad/crashpad/util/misc/uuid_test.cc +++ b/third_party/crashpad/crashpad/util/misc/uuid_test.cc
@@ -214,6 +214,31 @@ // Mixed case. uuid.InitializeFromString("5762C15D-50b5-4171-a2e9-7429C9EC6CAB"); EXPECT_EQ(uuid.ToString(), "5762c15d-50b5-4171-a2e9-7429c9ec6cab"); + + // Test accepting a StringPiece16. + // clang-format off + static constexpr base::char16 kChar16UUID[] = { + 'f', '3', '2', 'e', '5', 'b', 'd', 'c', '-', + '2', '6', '8', '1', '-', + '4', 'c', '7', '3', '-', + 'a', '4', 'e', '6', '-', + '3', '3', '3', 'f', 'f', 'd', '3', '3', 'b', '3', '3', '3', + }; + // clang-format on + EXPECT_TRUE(uuid.InitializeFromString( + base::StringPiece16(kChar16UUID, arraysize(kChar16UUID)))); + EXPECT_EQ(uuid.ToString(), "f32e5bdc-2681-4c73-a4e6-333ffd33b333"); + +#if defined(OS_WIN) + // Test accepting a StringPiece16 via L"" literals on Windows. + EXPECT_TRUE( + uuid.InitializeFromString(L"F32E5BDC-2681-4C73-A4E6-444FFD44B444")); + EXPECT_EQ(uuid.ToString(), "f32e5bdc-2681-4c73-a4e6-444ffd44b444"); + + EXPECT_TRUE( + uuid.InitializeFromString(L"5762C15D-50b5-4171-a2e9-5555C5EC5CAB")); + EXPECT_EQ(uuid.ToString(), "5762c15d-50b5-4171-a2e9-5555c5ec5cab"); +#endif // OS_WIN } #if defined(OS_WIN)
diff --git a/third_party/crashpad/crashpad/util/net/http_transport_fuchsia.cc b/third_party/crashpad/crashpad/util/net/http_transport_none.cc similarity index 100% rename from third_party/crashpad/crashpad/util/net/http_transport_fuchsia.cc rename to third_party/crashpad/crashpad/util/net/http_transport_none.cc
diff --git a/third_party/crashpad/crashpad/util/posix/signals.h b/third_party/crashpad/crashpad/util/posix/signals.h index ade093bfa..dc55059 100644 --- a/third_party/crashpad/crashpad/util/posix/signals.h +++ b/third_party/crashpad/crashpad/util/posix/signals.h
@@ -24,6 +24,9 @@ //! \brief Utilities for handling POSIX signals. class Signals { public: + //! \brief A signal number used by Crashpad to simulate signals. + static constexpr int kSimulatedSigno = -1; + //! \brief The type used for `struct sigaction::sa_sigaction`. using Handler = void (*)(int, siginfo_t*, void*);
diff --git a/third_party/crashpad/crashpad/util/thread/stoppable.h b/third_party/crashpad/crashpad/util/thread/stoppable.h new file mode 100644 index 0000000..e7a5127 --- /dev/null +++ b/third_party/crashpad/crashpad/util/thread/stoppable.h
@@ -0,0 +1,39 @@ +// Copyright 2018 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_UTIL_THREAD_STOPPABLE_H_ +#define CRASHPAD_UTIL_THREAD_STOPPABLE_H_ + +#include "base/macros.h" + +namespace crashpad { + +//! \brief An interface for operations that may be Started and Stopped. +class Stoppable { + public: + virtual ~Stoppable() = default; + + //! \brief Starts the operation. + virtual void Start() = 0; + + //! \brief Stops the operation. + virtual void Stop() = 0; + + protected: + Stoppable() = default; +}; + +} // namespace crashpad + +#endif // CRASHPAD_UTIL_THREAD_STOPPABLE_H_
diff --git a/third_party/crashpad/crashpad/util/util.gyp b/third_party/crashpad/crashpad/util/util.gyp index 0000ee2..e0394e2 100644 --- a/third_party/crashpad/crashpad/util/util.gyp +++ b/third_party/crashpad/crashpad/util/util.gyp
@@ -73,6 +73,8 @@ 'linux/ptrace_connection.h', 'linux/ptracer.cc', 'linux/ptracer.h', + 'linux/scoped_pr_set_ptracer.cc', + 'linux/scoped_pr_set_ptracer.h', 'linux/scoped_ptrace_attach.cc', 'linux/scoped_ptrace_attach.h', 'linux/thread_info.cc', @@ -125,10 +127,15 @@ 'misc/address_types.h', 'misc/arraysize_unsafe.h', 'misc/as_underlying_type.h', + 'misc/capture_context.h', + 'misc/capture_context_linux.S', + 'misc/capture_context_mac.S', + 'misc/capture_context_win.asm', 'misc/clock.h', 'misc/clock_mac.cc', 'misc/clock_posix.cc', 'misc/clock_win.cc', + 'misc/elf_note_types.h', 'misc/from_pointer_cast.h', 'misc/implicit_cast.h', 'misc/initialization_state.h', @@ -223,6 +230,7 @@ 'synchronization/semaphore_posix.cc', 'synchronization/semaphore_win.cc', 'synchronization/semaphore.h', + 'thread/stoppable.h', 'thread/thread.cc', 'thread/thread.h', 'thread/thread_log_messages.cc', @@ -232,8 +240,6 @@ 'thread/worker_thread.cc', 'thread/worker_thread.h', 'win/address_types.h', - 'win/capture_context.asm', - 'win/capture_context.h', 'win/checked_win_address_range.h', 'win/command_line.cc', 'win/command_line.h', @@ -340,6 +346,8 @@ '$(SDKROOT)/usr/lib/libbsm.dylib', ], }, + }, { # else: OS!=mac + 'sources!': [ 'misc/capture_context_mac.S' ], }], ['OS=="win"', { 'link_settings': { @@ -369,7 +377,7 @@ ], }, { # else: OS!="win" 'sources!': [ - 'win/capture_context.asm', + 'misc/capture_context_win.asm', 'win/safe_terminate_process.asm', ], }], @@ -381,6 +389,7 @@ }, }, { # else: OS!="linux" 'sources!': [ + 'misc/capture_context_linux.S', 'net/http_transport_libcurl.cc', ], }], @@ -394,6 +403,7 @@ ['OS=="android"', { 'sources/': [ ['include', '^linux/'], + ['include', '^misc/capture_context_linux\\.S$'], ['include', '^misc/paths_linux\\.cc$'], ['include', '^posix/process_info_linux\\.cc$'], ['include', '^process/process_memory_linux\\.cc$'],
diff --git a/third_party/crashpad/crashpad/util/util_test.gyp b/third_party/crashpad/crashpad/util/util_test.gyp index a287327..d07dc82a 100644 --- a/third_party/crashpad/crashpad/util/util_test.gyp +++ b/third_party/crashpad/crashpad/util/util_test.gyp
@@ -67,6 +67,11 @@ 'mach/symbolic_constants_mach_test.cc', 'mach/task_memory_test.cc', 'misc/arraysize_unsafe_test.cc', + 'misc/capture_context_test.cc', + 'misc/capture_context_test_util.h', + 'misc/capture_context_test_util_linux.cc', + 'misc/capture_context_test_util_mac.cc', + 'misc/capture_context_test_util_win.cc', 'misc/clock_test.cc', 'misc/from_pointer_cast_test.cc', 'misc/initialization_state_dcheck_test.cc', @@ -105,7 +110,6 @@ 'thread/thread_log_messages_test.cc', 'thread/thread_test.cc', 'thread/worker_thread_test.cc', - 'win/capture_context_test.cc', 'win/command_line_test.cc', 'win/critical_section_with_debug_info_test.cc', 'win/exception_handler_server_test.cc', @@ -156,6 +160,7 @@ ['OS=="android"', { 'sources/': [ ['include', '^linux/'], + ['include', '^misc/capture_context_test_util_linux\\.cc$'], ], }], ],
diff --git a/third_party/crashpad/crashpad/util/win/capture_context.h b/third_party/crashpad/crashpad/util/win/capture_context.h deleted file mode 100644 index 2f501f8..0000000 --- a/third_party/crashpad/crashpad/util/win/capture_context.h +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2015 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_CLIENT_CAPTURE_CONTEXT_WIN_H_ -#define CRASHPAD_CLIENT_CAPTURE_CONTEXT_WIN_H_ - -#include <windows.h> - -namespace crashpad { - -//! \brief Saves the CPU context. -//! -//! The CPU context will be captured as accurately and completely as possible, -//! containing an atomic snapshot at the point of this function’s return. This -//! function does not modify any registers. -//! -//! This function captures all integer registers as well as the floating-point -//! and vector (SSE) state. It does not capture debug registers, which are -//! inaccessible by user code. -//! -//! This function is a replacement for `RtlCaptureContext()`, which contains -//! bugs and limitations. On 32-bit x86, `RtlCaptureContext()` requires that -//! `ebp` be used as a frame pointer, and returns `ebp`, `esp`, and `eip` out of -//! sync with the other registers. Both the 32-bit x86 and 64-bit x86_64 -//! versions of `RtlCaptureContext()` capture only the state of the integer -//! registers, ignoring floating-point and vector state. -//! -//! \param[out] context The structure to store the context in. -//! -//! \note On x86_64, the value for `rcx` will be populated with the address of -//! this function’s argument, as mandated by the ABI. -void CaptureContext(CONTEXT* context); - -} // namespace crashpad - -#endif // CRASHPAD_CLIENT_CAPTURE_CONTEXT_WIN_H_
diff --git a/third_party/crashpad/crashpad/util/win/capture_context_test.cc b/third_party/crashpad/crashpad/util/win/capture_context_test.cc deleted file mode 100644 index 292e4749..0000000 --- a/third_party/crashpad/crashpad/util/win/capture_context_test.cc +++ /dev/null
@@ -1,180 +0,0 @@ -// Copyright 2015 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 "util/win/capture_context.h" - -#include <stdint.h> -#include <sys/types.h> - -#include <algorithm> - -#include "base/macros.h" -#include "build/build_config.h" -#include "gtest/gtest.h" - -namespace crashpad { -namespace test { -namespace { - -// If the context structure has fields that tell whether it’s valid, such as -// magic numbers or size fields, sanity-checks those fields for validity with -// fatal gtest assertions. For other fields, where it’s possible to reason about -// their validity based solely on their contents, sanity-checks via nonfatal -// gtest assertions. -void SanityCheckContext(const CONTEXT& context) { -#if defined(ARCH_CPU_X86) - constexpr uint32_t must_have = CONTEXT_i386 | - CONTEXT_CONTROL | - CONTEXT_INTEGER | - CONTEXT_SEGMENTS | - CONTEXT_FLOATING_POINT; - ASSERT_EQ(context.ContextFlags & must_have, must_have); - constexpr uint32_t may_have = CONTEXT_EXTENDED_REGISTERS; - ASSERT_EQ(context.ContextFlags & ~(must_have | may_have), 0u); -#elif defined(ARCH_CPU_X86_64) - ASSERT_EQ(context.ContextFlags, - static_cast<DWORD>(CONTEXT_AMD64 | CONTEXT_CONTROL | - CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT)); -#endif - -#if defined(ARCH_CPU_X86_FAMILY) - // Many bit positions in the flags register are reserved and will always read - // a known value. Most reserved bits are always 0, but bit 1 is always 1. - // Check that the reserved bits are all set to their expected values. Note - // that the set of reserved bits may be relaxed over time with newer CPUs, and - // that this test may need to be changed to reflect these developments. The - // current set of reserved bits are 1, 3, 5, 15, and 22 and higher. See Intel - // Software Developer’s Manual, Volume 1: Basic Architecture (253665-055), - // 3.4.3 “EFLAGS Register”, and AMD Architecture Programmer’s Manual, Volume - // 2: System Programming (24593-3.25), 3.1.6 “RFLAGS Register”. - EXPECT_EQ(context.EFlags & 0xffc0802a, 2u); - - // CaptureContext() doesn’t capture debug registers, so make sure they read 0. - EXPECT_EQ(context.Dr0, 0u); - EXPECT_EQ(context.Dr1, 0u); - EXPECT_EQ(context.Dr2, 0u); - EXPECT_EQ(context.Dr3, 0u); - EXPECT_EQ(context.Dr6, 0u); - EXPECT_EQ(context.Dr7, 0u); -#endif - -#if defined(ARCH_CPU_X86) - // fxsave doesn’t write these bytes. - for (size_t i = 464; i < arraysize(context.ExtendedRegisters); ++i) { - SCOPED_TRACE(i); - EXPECT_EQ(context.ExtendedRegisters[i], 0); - } -#elif defined(ARCH_CPU_X86_64) - // mxcsr shows up twice in the context structure. Make sure the values are - // identical. - EXPECT_EQ(context.FltSave.MxCsr, context.MxCsr); - - // fxsave doesn’t write these bytes. - for (size_t i = 0; i < arraysize(context.FltSave.Reserved4); ++i) { - SCOPED_TRACE(i); - EXPECT_EQ(context.FltSave.Reserved4[i], 0); - } - - // CaptureContext() doesn’t use these fields. - EXPECT_EQ(context.P1Home, 0u); - EXPECT_EQ(context.P2Home, 0u); - EXPECT_EQ(context.P3Home, 0u); - EXPECT_EQ(context.P4Home, 0u); - EXPECT_EQ(context.P5Home, 0u); - EXPECT_EQ(context.P6Home, 0u); - for (size_t i = 0; i < arraysize(context.VectorRegister); ++i) { - SCOPED_TRACE(i); - EXPECT_EQ(context.VectorRegister[i].Low, 0u); - EXPECT_EQ(context.VectorRegister[i].High, 0u); - } - EXPECT_EQ(context.VectorControl, 0u); - EXPECT_EQ(context.DebugControl, 0u); - EXPECT_EQ(context.LastBranchToRip, 0u); - EXPECT_EQ(context.LastBranchFromRip, 0u); - EXPECT_EQ(context.LastExceptionToRip, 0u); - EXPECT_EQ(context.LastExceptionFromRip, 0u); -#endif -} - -// A CPU-independent function to return the program counter. -uintptr_t ProgramCounterFromContext(const CONTEXT& context) { -#if defined(ARCH_CPU_X86) - return context.Eip; -#elif defined(ARCH_CPU_X86_64) - return context.Rip; -#endif -} - -// A CPU-independent function to return the stack pointer. -uintptr_t StackPointerFromContext(const CONTEXT& context) { -#if defined(ARCH_CPU_X86) - return context.Esp; -#elif defined(ARCH_CPU_X86_64) - return context.Rsp; -#endif -} - -void TestCaptureContext() { - CONTEXT context_1; - CaptureContext(&context_1); - - { - SCOPED_TRACE("context_1"); - ASSERT_NO_FATAL_FAILURE(SanityCheckContext(context_1)); - } - - // The program counter reference value is this function’s address. The - // captured program counter should be slightly greater than or equal to the - // reference program counter. - uintptr_t pc = ProgramCounterFromContext(context_1); - - // Declare sp and context_2 here because all local variables need to be - // declared before computing the stack pointer reference value, so that the - // reference value can be the lowest value possible. - uintptr_t sp; - CONTEXT context_2; - - // The stack pointer reference value is the lowest address of a local variable - // in this function. The captured program counter will be slightly less than - // or equal to the reference stack pointer. - const uintptr_t kReferenceSP = - std::min(std::min(reinterpret_cast<uintptr_t>(&context_1), - reinterpret_cast<uintptr_t>(&context_2)), - std::min(reinterpret_cast<uintptr_t>(&pc), - reinterpret_cast<uintptr_t>(&sp))); - sp = StackPointerFromContext(context_1); - EXPECT_LT(kReferenceSP - sp, 512u); - - // Capture the context again, expecting that the stack pointer stays the same - // and the program counter increases. Strictly speaking, there’s no guarantee - // that these conditions will hold, although they do for known compilers even - // under typical optimization. - CaptureContext(&context_2); - - { - SCOPED_TRACE("context_2"); - ASSERT_NO_FATAL_FAILURE(SanityCheckContext(context_2)); - } - - EXPECT_EQ(StackPointerFromContext(context_2), sp); - EXPECT_GT(ProgramCounterFromContext(context_2), pc); -} - -TEST(CaptureContextWin, CaptureContext) { - ASSERT_NO_FATAL_FAILURE(TestCaptureContext()); -} - -} // namespace -} // namespace test -} // namespace crashpad
diff --git a/third_party/leveldatabase/env_chromium.cc b/third_party/leveldatabase/env_chromium.cc index 78a96b2..caf7461 100644 --- a/third_party/leveldatabase/env_chromium.cc +++ b/third_party/leveldatabase/env_chromium.cc
@@ -532,7 +532,7 @@ Options::Options() { // Note: Ensure that these default values correspond to those in -// components/leveldb/public/interfaces/leveldb.mojom. +// components/services/leveldb/public/interfaces/leveldb.mojom. // TODO(cmumford) Create struct-trait for leveldb.mojom.OpenOptions to force // users to pass in a leveldb_env::Options instance (and it's defaults). //
diff --git a/tools/bisect_repackage/bisect_repackage.py b/tools/bisect_repackage/bisect_repackage.py index 22b1bfb..77e91e6 100644 --- a/tools/bisect_repackage/bisect_repackage.py +++ b/tools/bisect_repackage/bisect_repackage.py
@@ -46,7 +46,6 @@ 'default_apps/', 'icudtl.dat', 'libclearkeycdm.so', - 'libclearkeycdmadapter.so', 'libwidevinecdm.so', 'libwidevinecdmadapter.so', 'locales/',
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index f5d2c6d..2eedbc8 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -7414,6 +7414,8 @@ <int value="5" label="kPrepareNewCrashReportFailed"/> <int value="6" label="kMinidumpWriteFailed"/> <int value="7" label="kFinishWritingCrashReportFailed"/> + <int value="8" label="kDirectPtraceFailed"/> + <int value="9" label="kBrokeredPtraceFailed"/> </enum> <enum name="CrashpadExceptionProcessingState">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 906d4b2..f725102 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -48508,7 +48508,6 @@ </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary>The time from the connection start to connection establish.</summary> </histogram> @@ -48518,7 +48517,6 @@ </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary>The time waiting to be ready to start connecting.</summary> </histogram> @@ -48529,7 +48527,6 @@ </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary> Each bucket is the number of connection type of socket stream. </summary> @@ -48542,7 +48539,6 @@ </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary>The time a socket stream was open.</summary> </histogram> @@ -48552,7 +48548,6 @@ </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary> Each bucket is the number of protocol type on socket stream. </summary> @@ -48564,7 +48559,6 @@ </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary>Number of bytes on a socket stream.</summary> </histogram> @@ -48574,7 +48568,6 @@ </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary>Number of reads on a socket stream.</summary> </histogram> @@ -48584,7 +48577,6 @@ </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary>Number of bytes on a socket stream.</summary> </histogram> @@ -48594,7 +48586,6 @@ </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary>Number of Write on a socket stream.</summary> </histogram> @@ -50131,7 +50122,6 @@ enum="WebSocketNewPerMessageDeflateContextTakeoverMode"> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary> Count the number of WebSockets that accepted permessage-deflate extension for each context take over mode. Used by the new Chromium-based WebSocket @@ -50142,7 +50132,6 @@ <histogram name="Net.WebSocket.Duration" units="ms"> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary> The time from a WebSocket is successfully opened until it's closed. Used to study how WebSockets are used. @@ -50152,7 +50141,6 @@ <histogram name="Net.WebSocket.ErrorCodes" enum="NetErrorCodes"> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary> Positive net error codes that WebSockets end with, including OK and ABORTED. </summary> @@ -50162,7 +50150,6 @@ enum="WebSocketNewHandshakeResult"> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary> Results of WebSocket handshakes. Use this histogram as a baseline for investigating feature usage counters. @@ -50172,7 +50159,6 @@ <histogram name="Net.WebSocket.ResponseCode" enum="HttpResponseCode"> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary>All HTTP status codes seen during WebSocket handshakes.</summary> </histogram> @@ -99981,7 +99967,6 @@ </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary> Count the number of changes to WebSocket.binaryType after the connection opened, per connection. Assignments that match the existing binaryType are @@ -99999,7 +99984,6 @@ </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary> Count the number of WebSocket handshake for each result. Use this histogram as a baseline for investigating feature usage counters. @@ -100009,7 +99993,6 @@ <histogram name="WebCore.WebSocket.MessageSize.Receive" units="bytes"> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary> The sizes of binary WebSocket messages received, broken down by type. One entry per message. Clamped to 100 MB. @@ -100019,7 +100002,6 @@ <histogram name="WebCore.WebSocket.MessageSize.Send" units="bytes"> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary> The sizes of binary WebSocket messages sent, broken down by type. One entry per message. Clamped to 100 MB. @@ -100034,7 +100016,6 @@ </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary> Count the number of WebSockets that accepted permessage-deflate extension for each context take over mode. Used by the old Blink-based WebSocket @@ -100045,7 +100026,6 @@ <histogram name="WebCore.WebSocket.ReceiveType" enum="WebSocketReceiveType"> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary> Count the number of messages for each message type and set binary type. </summary> @@ -100054,7 +100034,6 @@ <histogram name="WebCore.WebSocket.SendType" enum="WebSocketSendType"> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> - <owner>tyoshino@chromium.org</owner> <summary> Count the number of send() method calls on WebSockets for each argument type. @@ -100069,7 +100048,6 @@ The support for ArrayBuffer was un-deprecated in the WHATWG spec for XHR, and subsequently un-deprecated in Blink. </obsolete> - <owner>tyoshino@chromium.org</owner> <owner>costan@gmail.com</owner> <summary> Count the number of XHR.send() calls for each argument type to see when we
diff --git a/tools/perf/core/results_dashboard.py b/tools/perf/core/results_dashboard.py index 2e626ae..16eec51 100755 --- a/tools/perf/core/results_dashboard.py +++ b/tools/perf/core/results_dashboard.py
@@ -32,6 +32,21 @@ CACHE_DIR = 'results_dashboard' CACHE_FILENAME = 'results_to_retry' +ERROR_NO_OAUTH_TOKEN = ( + 'No oauth token provided, cannot upload HistogramSet. Discarding.') + + +class SendResultException(Exception): + pass + + +class SendResultsRetryException(SendResultException): + pass + + +class SendResultsFatalException(SendResultException): + pass + def SendResults(data, url, tmp_dir, json_url_file=None, send_as_histograms=False, oauth_token=None): @@ -73,8 +88,6 @@ for error in errors: print error if fatal_error: - print 'Error uploading to dashboard.' - print '@@@STEP_EXCEPTION@@@' return False return True @@ -134,25 +147,20 @@ errors.append('Could not parse JSON: %s' % line) continue - if is_histogramset: - # TODO(eakuefner): Remove this discard logic once all bots use histograms. - if oauth_token is None: - print 'No oauth token provided, cannot upload HistogramSet. Discarding.' - fatal_error = True - break - error = _SendHistogramJson(url, json.dumps(data), oauth_token) - else: - error = _SendResultsJson(url, json.dumps(data)) + data_type = ('histogram' if is_histogramset else 'chartjson') - # If the dashboard returned an error, we will re-try next time. - if error: - if 'HTTPError: 400' in error: - # If the remote app rejects the JSON, it's probably malformed, - # so we don't want to retry it. - print 'Discarding JSON, error:\n%s' % error - fatal_error = True - break + try: + if is_histogramset: + # TODO(eakuefner): Remove this discard logic once all bots use + # histograms. + if oauth_token is None: + raise SendResultsFatalException(ERROR_NO_OAUTH_TOKEN) + _SendHistogramJson(url, json.dumps(data), oauth_token) + else: + _SendResultsJson(url, json.dumps(data)) + except SendResultsRetryException as e: + error = 'Error while uploading %s data: %s' % (data_type, str(e)) if index != len(cache_lines) - 1: # The very last item in the cache_lines list is the new results line. # If this line is not the new results line, then this results line @@ -163,6 +171,17 @@ lines_to_retry = [l.strip() for l in cache_lines[index:] if l.strip()] errors.append(error) break + except SendResultsFatalException as e: + error = 'Error uploading %s data: %s' % (data_type, str(e)) + errors.append(error) + fatal_error = True + break + except Exception: + error = 'Unexpected error while uploading %s data: %s' % ( + data_type, traceback.format_exc()) + errors.append(error) + fatal_error = True + break # Write any failing requests to the cache file. cache = open(cache_file_name, 'wb') @@ -471,8 +490,13 @@ try: urllib2.urlopen(req) except (urllib2.HTTPError, urllib2.URLError, httplib.HTTPException): - return traceback.format_exc() - return None + error = traceback.format_exc() + + if 'HTTPError: 400' in error: + # If the remote app rejects the JSON, it's probably malformed, + # so we don't want to retry it. + raise SendResultsFatalException('Discarding JSON, error:\n%s' % error) + raise SendResultsRetryException() def _Httplib2Request(url, data, oauth_token): data = urllib.urlencode({'data': data}) @@ -498,14 +522,19 @@ None if successful, or an error string if there were errors. """ try: - _, content = _Httplib2Request(url, histogramset_json, oauth_token) - result = json.loads(content) or {} - error = result.get('error') - if error is not None: - return 'HTTP error: %s\n' % error - except (httplib2.HttpLib2Error, ValueError): - return traceback.format_exc() - return None + response, _ = _Httplib2Request(url, histogramset_json, oauth_token) + + # A 500 is presented on an exception on the dashboard side, timeout, + # exception, etc. The dashboard can also send back 400 and 403, we could + # recover from 403 (auth error), but 400 is generally malformed data. + if response.status == 403: + raise SendResultsRetryException(traceback.format_exc()) + + if response.status != 200: + raise SendResultsFatalException('HTTP Response %d: %s' % ( + response.status, response.reason)) + except httplib2.HttpLib2Error: + raise SendResultsRetryException(traceback.format_exc()) def _DashboardUrl(url, data): """Returns link to the dashboard if possible.
diff --git a/tools/perf/core/upload_results_to_perf_dashboard.py b/tools/perf/core/upload_results_to_perf_dashboard.py index db7b06b..00cd771a 100755 --- a/tools/perf/core/upload_results_to_perf_dashboard.py +++ b/tools/perf/core/upload_results_to_perf_dashboard.py
@@ -137,7 +137,8 @@ if dashboard_json: if options.output_json_file: with open(options.output_json_file, 'w') as output_file: - json.dump(dashboard_json, output_file) + json.dump(dashboard_json, output_file, + indent=4, separators=(',', ': ')) if not results_dashboard.SendResults( dashboard_json, options.results_url,
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 6ac39ab..ac0e4ef8 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -36,6 +36,7 @@ <item id="cast_socket" hash_code="115192205" type="0" content_hash_code="63056899" os_list="linux,windows" file_path="components/cast_channel/cast_socket.cc"/> <item id="cast_udp_socket" hash_code="22573197" type="0" content_hash_code="75328301" os_list="linux,windows" file_path="media/cast/net/udp_socket_client.cc"/> <item id="cast_udp_transport" hash_code="5576536" type="0" content_hash_code="107643273" os_list="linux,windows" file_path="media/cast/net/udp_transport_impl.cc"/> + <item id="certificate_reporting_service_test" hash_code="98123372" type="0" content_hash_code="136253658" os_list="linux,windows" file_path="chrome/browser/safe_browsing/certificate_reporting_service.cc"/> <item id="certificate_verifier" hash_code="113553577" type="0" content_hash_code="62346354" os_list="linux,windows" file_path="net/cert_net/cert_net_fetcher_impl.cc"/> <item id="chrome_apps_socket_api" hash_code="8591273" type="0" content_hash_code="70868355" os_list="linux,windows" file_path="extensions/browser/api/socket/socket.cc"/> <item id="chrome_cleaner" hash_code="27071967" type="0" content_hash_code="111240292" os_list="windows" file_path="chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win.cc"/> @@ -177,8 +178,9 @@ <item id="privet_http_impl" hash_code="71251498" type="0" content_hash_code="107348604" os_list="linux,windows" file_path="chrome/browser/printing/cloud_print/privet_http_impl.cc"/> <item id="profile_avatar" hash_code="51164680" type="0" content_hash_code="113550845" os_list="linux,windows" file_path="chrome/browser/profiles/profile_avatar_downloader.cc"/> <item id="profile_resetter_upload" hash_code="105330607" type="0" content_hash_code="129329171" os_list="linux,windows" file_path="chrome/browser/profile_resetter/reset_report_uploader.cc"/> - <item id="proxy_config_direct" hash_code="119015679" type="0" content_hash_code="131944978" os_list="linux,windows" file_path="net/proxy_resolution/proxy_config_with_annotation.cc"/> - <item id="proxy_config_settings" hash_code="136468456" type="0" content_hash_code="136747792" os_list="linux,windows" file_path="components/proxy_config/pref_proxy_config_tracker_impl.cc"/> + <item id="proxy_config_direct" hash_code="119015679" type="0" content_hash_code="119931568" os_list="linux,windows" file_path="net/proxy_resolution/proxy_config_with_annotation.cc"/> + <item id="proxy_config_headless" hash_code="133221587" type="0" content_hash_code="77459277" os_list="linux,windows" file_path="headless/lib/browser/headless_url_request_context_getter.cc"/> + <item id="proxy_config_settings" hash_code="136468456" type="0" content_hash_code="19527377" os_list="linux,windows" file_path="components/proxy_config/pref_proxy_config_tracker_impl.cc"/> <item id="proxy_script_fetcher" hash_code="37531401" type="0" content_hash_code="31866133" os_list="linux,windows" file_path="net/proxy_resolution/pac_file_fetcher_impl.cc"/> <item id="puch_client_channel" hash_code="34459548" type="0" content_hash_code="92475475" os_list="linux,windows" file_path="components/invalidation/impl/push_client_channel.cc"/> <item id="quic_chromium_incoming_session" hash_code="87635401" type="0" content_hash_code="78573093" os_list="linux,windows" file_path="net/quic/chromium/quic_chromium_client_session.cc"/>
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc index 98adab0f..b5c83d4 100644 --- a/ui/app_list/views/search_box_view.cc +++ b/ui/app_list/views/search_box_view.cc
@@ -300,6 +300,7 @@ search_model_->search_box(); search_box()->set_placeholder_text(search_box_model->hint_text()); search_box()->SetAccessibleName(search_box_model->accessible_name()); + SchedulePaint(); } void SearchBoxView::SelectionModelChanged() {
diff --git a/ui/events/event_rewriter_unittest.cc b/ui/events/event_rewriter_unittest.cc index d649232f..ae9abce 100644 --- a/ui/events/event_rewriter_unittest.cc +++ b/ui/events/event_rewriter_unittest.cc
@@ -11,28 +11,14 @@ #include "base/macros.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/keycodes/dom/dom_code.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "ui/events/test/test_event_processor.h" namespace ui { namespace { -// To test the handling of |EventRewriter|s through |EventSource|, -// we rewrite and test event types. -class TestEvent : public Event { - public: - explicit TestEvent(EventType type) - : Event(type, base::TimeTicks(), 0), unique_id_(next_unique_id_++) {} - ~TestEvent() override {} - int unique_id() const { return unique_id_; } - - private: - static int next_unique_id_; - int unique_id_; -}; - -int TestEvent::next_unique_id_ = 0; - // TestEventRewriteProcessor is set up with a sequence of event types, // and fails if the events received via OnEventFromSource() do not match // this sequence. These expected event types are consumed on receipt. @@ -58,6 +44,28 @@ DISALLOW_COPY_AND_ASSIGN(TestEventRewriteProcessor); }; +std::unique_ptr<Event> CreateEventForType(EventType type) { + switch (type) { + case ET_CANCEL_MODE: + return std::make_unique<CancelModeEvent>(); + case ET_MOUSE_DRAGGED: + case ET_MOUSE_PRESSED: + case ET_MOUSE_RELEASED: + return std::make_unique<MouseEvent>(type, gfx::Point(), gfx::Point(), + base::TimeTicks::Now(), 0, 0); + case ET_KEY_PRESSED: + case ET_KEY_RELEASED: + return std::make_unique<KeyEvent>(type, ui::VKEY_TAB, DomCode::NONE, 0); + case ET_SCROLL_FLING_CANCEL: + case ET_SCROLL_FLING_START: + return std::make_unique<ScrollEvent>( + type, gfx::Point(), base::TimeTicks::Now(), 0, 0, 0, 0, 0, 0); + default: + NOTREACHED() << type; + return nullptr; + } +} + // Trivial EventSource that does nothing but send events. class TestEventRewriteSource : public EventSource { public: @@ -65,7 +73,7 @@ : processor_(processor) {} EventProcessor* GetEventSink() override { return processor_; } void Send(EventType type) { - std::unique_ptr<Event> event(new TestEvent(type)); + auto event = CreateEventForType(type); SendEventToSink(event.get()); } @@ -88,7 +96,7 @@ const Event& event, std::unique_ptr<Event>* rewritten_event) override { if (status_ == EVENT_REWRITE_REWRITTEN) - rewritten_event->reset(new TestEvent(type_)); + *rewritten_event = CreateEventForType(type_); return status_; } EventRewriteStatus NextDispatchEvent( @@ -123,10 +131,10 @@ return EVENT_REWRITE_CONTINUE; if ((find->second.status == EVENT_REWRITE_REWRITTEN) || (find->second.status == EVENT_REWRITE_DISPATCH_ANOTHER)) { - last_rewritten_event_ = new TestEvent(find->second.type); - rewritten_event->reset(last_rewritten_event_); + *rewritten_event = CreateEventForType(find->second.type); + last_rewritten_event_ = rewritten_event->get(); } else { - last_rewritten_event_ = 0; + last_rewritten_event_ = nullptr; } state_ = find->second.state; return find->second.status; @@ -135,10 +143,8 @@ const Event& last_event, std::unique_ptr<Event>* new_event) override { EXPECT_TRUE(last_rewritten_event_); - const TestEvent* arg_last = static_cast<const TestEvent*>(&last_event); - EXPECT_EQ(last_rewritten_event_->unique_id(), arg_last->unique_id()); - const TestEvent* arg_new = static_cast<const TestEvent*>(new_event->get()); - EXPECT_FALSE(arg_new && arg_last->unique_id() == arg_new->unique_id()); + EXPECT_EQ(last_rewritten_event_, &last_event); + EXPECT_FALSE(new_event->get() && new_event->get() == &last_event); return RewriteEvent(last_event, new_event); } @@ -151,7 +157,7 @@ }; typedef std::map<RewriteCase, RewriteResult> RewriteRules; RewriteRules rules_; - TestEvent* last_rewritten_event_; + Event* last_rewritten_event_; int state_; };
diff --git a/ui/events/event_source.cc b/ui/events/event_source.cc index fcdffe5d..e45be7c 100644 --- a/ui/events/event_source.cc +++ b/ui/events/event_source.cc
@@ -11,6 +11,17 @@ #include "ui/events/event_sink.h" namespace ui { +namespace { + +bool IsLocatedEventWithDifferentLocations(const Event& event) { + if (!event.IsLocatedEvent()) + return false; + const LocatedEvent* located_event = event.AsLocatedEvent(); + return located_event->target() && + located_event->location_f() != located_event->root_location_f(); +} + +} // namespace EventSource::EventSource() {} @@ -30,12 +41,23 @@ } EventDispatchDetails EventSource::SendEventToSink(Event* event) { + std::unique_ptr<ui::Event> event_for_rewriting_ptr; + Event* event_for_rewriting = event; + if (!rewriter_list_.empty() && IsLocatedEventWithDifferentLocations(*event)) { + // EventRewriters don't expect an event with differing location and + // root-location (because they don't honor the target). Provide such an + // event for rewriters. + event_for_rewriting_ptr = ui::Event::Clone(*event); + event_for_rewriting_ptr->AsLocatedEvent()->set_location_f( + event_for_rewriting_ptr->AsLocatedEvent()->root_location_f()); + event_for_rewriting = event_for_rewriting_ptr.get(); + } std::unique_ptr<Event> rewritten_event; EventRewriteStatus status = EVENT_REWRITE_CONTINUE; EventRewriterList::const_iterator it = rewriter_list_.begin(), end = rewriter_list_.end(); for (; it != end; ++it) { - status = (*it)->RewriteEvent(*event, &rewritten_event); + status = (*it)->RewriteEvent(*event_for_rewriting, &rewritten_event); if (status == EVENT_REWRITE_DISCARD) { CHECK(!rewritten_event); return EventDispatchDetails();
diff --git a/ui/gfx/skia_paint_util.cc b/ui/gfx/skia_paint_util.cc index df9dcded..83753af 100644 --- a/ui/gfx/skia_paint_util.cc +++ b/ui/gfx/skia_paint_util.cc
@@ -7,7 +7,7 @@ #include "base/memory/ptr_util.h" #include "cc/paint/paint_image_builder.h" #include "third_party/skia/include/core/SkColorFilter.h" -#include "third_party/skia/include/effects/SkBlurMaskFilter.h" +#include "third_party/skia/include/core/SkMaskFilter.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "third_party/skia/include/effects/SkLayerDrawLooper.h" #include "ui/gfx/image/image_skia_rep.h" @@ -87,11 +87,10 @@ SkIntToScalar(shadow.y())); SkPaint* paint = looper_builder.addLayer(layer_info); - // SkBlurMaskFilter's blur radius defines the range to extend the blur from + // Skia's blur radius defines the range to extend the blur from // original mask, which is half of blur amount as defined in ShadowValue. - paint->setMaskFilter(SkBlurMaskFilter::Make( - kNormal_SkBlurStyle, RadiusToSigma(shadow.blur() / 2), - SkBlurMaskFilter::kHighQuality_BlurFlag)); + paint->setMaskFilter(SkMaskFilter::MakeBlur( + kNormal_SkBlurStyle, RadiusToSigma(shadow.blur() / 2))); paint->setColorFilter( SkColorFilter::MakeModeFilter(shadow.color(), SkBlendMode::kSrcIn)); }
diff --git a/ui/gfx/skia_util.cc b/ui/gfx/skia_util.cc index 2fbae691..db2856f 100644 --- a/ui/gfx/skia_util.cc +++ b/ui/gfx/skia_util.cc
@@ -12,7 +12,6 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColorPriv.h" #include "third_party/skia/include/core/SkUnPreMultiply.h" -#include "third_party/skia/include/effects/SkBlurMaskFilter.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "third_party/skia/include/effects/SkLayerDrawLooper.h" #include "ui/gfx/geometry/quad_f.h"
diff --git a/ui/ozone/platform/wayland/fake_server.cc b/ui/ozone/platform/wayland/fake_server.cc index 6a34b6a..7eae750 100644 --- a/ui/ozone/platform/wayland/fake_server.cc +++ b/ui/ozone/platform/wayland/fake_server.cc
@@ -356,26 +356,31 @@ obj->resource_ = nullptr; } +template <class T> +void SetImplementation(wl_resource* resource, + const void* implementation, + T* user_data) { + wl_resource_set_implementation(resource, implementation, user_data, + &ServerObject::OnResourceDestroyed); +} + MockXdgSurface::MockXdgSurface(wl_resource* resource, const void* implementation) : ServerObject(resource) { - wl_resource_set_implementation(resource, implementation, this, - &ServerObject::OnResourceDestroyed); + SetImplementation(resource, implementation, this); } MockXdgSurface::~MockXdgSurface() {} MockXdgTopLevel::MockXdgTopLevel(wl_resource* resource) : MockXdgSurface(resource, &zxdg_surface_v6_impl) { - wl_resource_set_implementation(resource, &zxdg_toplevel_v6_impl, this, - &ServerObject::OnResourceDestroyed); + SetImplementation(resource, &zxdg_toplevel_v6_impl, this); } MockXdgTopLevel::~MockXdgTopLevel() {} MockSurface::MockSurface(wl_resource* resource) : ServerObject(resource) { - wl_resource_set_implementation(resource, &surface_impl, this, - &ServerObject::OnResourceDestroyed); + SetImplementation(resource, &surface_impl, this); } MockSurface::~MockSurface() { @@ -390,22 +395,19 @@ } MockPointer::MockPointer(wl_resource* resource) : ServerObject(resource) { - wl_resource_set_implementation(resource, &pointer_impl, this, - &ServerObject::OnResourceDestroyed); + SetImplementation(resource, &pointer_impl, this); } MockPointer::~MockPointer() {} MockKeyboard::MockKeyboard(wl_resource* resource) : ServerObject(resource) { - wl_resource_set_implementation(resource, &keyboard_impl, this, - &ServerObject::OnResourceDestroyed); + SetImplementation(resource, &keyboard_impl, this); } MockKeyboard::~MockKeyboard() {} MockTouch::MockTouch(wl_resource* resource) : ServerObject(resource) { - wl_resource_set_implementation(resource, &touch_impl, this, - &ServerObject::OnResourceDestroyed); + SetImplementation(resource, &touch_impl, this); } MockTouch::~MockTouch() {} @@ -442,8 +444,7 @@ } if (!global->resource_) global->resource_ = resource; - wl_resource_set_implementation(resource, global->implementation_, global, - &Global::OnResourceDestroyed); + SetImplementation(resource, global->implementation_, global); global->OnBind(); }
diff --git a/url/run_all_unittests.cc b/url/run_all_unittests.cc index fcafd03..5f577fd3 100644 --- a/url/run_all_unittests.cc +++ b/url/run_all_unittests.cc
@@ -24,5 +24,5 @@ return base::LaunchUnitTests( argc, argv, - base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); + base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite))); }